программирование

Минус ноль в JavaScript

Я, конечно, знаю, что JavaScript хранит числа по стандарту IEEE 754, но всё больше как-то теоретически. То есть, я знаю, что в языке есть NaN, бесконечности с разным знаком…

Но вот о существовании минус нуля я как-то не думал, хотя знал, что он существует. Но его существование было для меня чем-то довольно абстрактным, не влияющим не реальную жизнь, потому что я мало что знал о его свойствах.

Но, оказывается, в редких случаях отрицательный ноль может себя проявлять иначе, чем ноль положительный.

Как вы можете получить минус ноль? Например, просто написав что-то вроде «-x», где в «x» оказался ноль. Или округлив отрицательное число: Math.ceil(-0.5). В стандарте положительный и отрицательный ноль равны, знак нуля не исчезает при умножении, делении и нахождении квадратного корня. То есть он довольно живуч, но малозаметен.

Похоже, что в реальном коде минус ноль может проявить себя в двух вещах: делении и операции atan2, именно так его и можно отличить от положительного нуля:

function isNegativeZero(x) {
    return x === 0 && (1 / x) === -Infinity
}

function isNegativeZeroToo(x) {
    return x === 0 && Math.atan2(x, x) < 0
}

60 комментариев

Пайтон обогнал PHP по популярности

Рейтинг языков (6.46КиБ)

Опубликован февральский рейтинг языков программирования. Пайтон обогнал PHP по популярности, кроме того, сильно сдал позиции Perl.

14 комментариев

Internet Explorer 9 RC

Вышел Internet Explorer 9 Release Candidate. Из значимых для веб-технологов изменений — добавили Geolocation API и кодек WebM в теге VIDEO.

Выход этого RC для меня печальное событие. Это значит, что в девятой версии не появится cache manifest, а я очень на это расчитывал. Это единственный браузер из современных, который не будет поддерживать эту интереснейшую технологию. Увы.

10 комментариев

Bogosort

Сегодня на собеседовании (я всё ещё ищу пайтонистов, ау) всплыли алгоритмы сортировки и я решил немного почитать на эту тему. Оказывается есть смешной алгоритм сортировки Bogosort, который на практике не применяется, а служит только иллюстративным целям:

Bogosort (также рандомная сортировка, сортировка ружья или обезьянья сортировка) является очень неэффективным алгоритмом сортировки. Её используют только в образовательных целях, противопоставляя другим, более реалистичным алгоритмам. Если bogosort использовать для сортировки колоды карт, то сначала в алгоритме нужно проверить, лежат ли все карты по порядку, и если не лежат, то подбросить колоду в воздух, проверить лежат ли теперь все карты по порядку, и повторять процесс, пока не отсортируется колода.

Я, для интереса, написал его на Пайтоне и поразвлекался с запускам на разных данных. Вот код, если интересно:

from random import shuffle
from itertools import izip, islice

def bogosorted(arr):
    for x, y in izip(islice(arr, 1, None), islice(arr, 0, len(arr) - 1)):
         if y > x: return False

    return True

def bogosort(arr):
    while arr and not bogosorted(arr):
        shuffle(arr)

    return arr


print bogosort([1, 1, 3, 2, 2, 2])

27 комментариев

Синтаксис @font-face, совместимый с IE

Без лишних вступлений:

@font-face {
    font-family: 'MyFontFamily';
    src: url('myfont-webfont.eot#') format('eot'), 
         url('myfont-webfont.woff') format('woff'), 
         url('myfont-webfont.ttf')  format('truetype'),
         url('myfont-webfont.svg#svgFontName') format('svg');
    }

У IE (до 9-й версии) был баг в обработке атрибута src, все дальнейшие атрибуты IE воспринимал как часть URL, пытался на него идти и получал 404.

Посмотрите на третью строку, видите там „#“? IE по-прежнему считает остальную часть частью URL, но URL теперь выглядит как-то так:

myfont-webfont.eot#’) format(’eot’)…и так далее…format(’svg’

Вот такой простой и красивый трюк.

Добавлено позднее: не все поняли. После решётки в адресе страницы идёт идентификатор внутри страницы. Эта часть на сервер на отсылается.

16 комментариев

У вас компьютер какого пола?

Шутка пару дней гуляет по интернету, я её только несколько улучшил — теперь компьютер сам называет свой пол и можно пускать из командной строки (программист я или копипастер?). Работает только на Windows.

Нажимаете Win+R (или просто запускаете из командной строки), копируете туда следующую строку:

mshta "javascript:close((V=(v=new ActiveXObject('SAPI.SpVoice')).GetVoices()).count&&v.Speak('Hello! I am '+V(0).GetAttribute('Gender')))"

Потом нажимаете «Enter» и слушаете.

У меня оба ноута — девочки.

22 комментария

JavaScript: небезопасная изоляция скриптов

Я смотрю многие начинают задумываться об изоляции JavaScript, подключаемых в контекст страницы. Например, вы подключаете какую-то чужую библиотеку (виджет) с чужого сайта, но не очень-то ему доверяете.

Сейчас считается, что безопасным методом является что-то вроде:

(function (window, alert) {
    alert('Функция «alert» изолирована и доступ к методу из «window» теперь получить нельзя');
})({}, function (){})

Это не правильно.

Такой вызов вас ни от чего не защищает, более того, можно запросто «восстановить справедливость» и получить изнутри такого скрипта доступ к оригинальному window:

<script>
(function(window, alert){
    alert('Пичалька');

    (function(){ with(this) {
        alert('Уже всё хорошо'); 
    }}).call(null);
})({}, function(){})
</script>

В общем случае идея такой изоляции — плохая. Я не видел ни одного удачного примера подобной изоляции и не смог придумать его самостоятельно.

13 комментариев

Внимание: MySQL считает, что буквы «ё» и «е» — одно и то же.

Увы, MySQL, если выбрать кодировку Unicode, считает, что «е» и «ё» — это одно и то же. Багом это не считается, в официальной таблице, где описано как MySQL 6.0 сравнивает символы, эти символы в одном ряду.

mysql> set names utf8 collate utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> select 'е'='ё', 'ё'='ѐ'\G
*************************** 1. row ***************************
'е'='ё': 1
'ё'='ѐ': 1
1 row in set (0.00 sec)

Самое печальное, это нелогичное поведение всплывает, если есть потребность перевести базу с CP1251 на UTF-8, так как в CP1251-то как раз всё хорошо:

mysql> set names cp1251;
Query OK, 0 rows affected (0.00 sec)

mysql> select 'е'='ё', 'ё'='ѐ'\G
*************************** 1. row ***************************
'е'='ё': 0
'ё'='ѐ': 0
1 row in set (0.00 sec)

Чем это может быть плохо? Например, у нас по какому-то текстовому полю имеется уникальный ключ. Для иллюстративности, пусть это будет словарь фамилий. Фамилии Рублев и Рублёв — разные, но MySQL так не считает (для простоты опускаю другие поля):

mysql> set names utf8 collate utf8_unicode_ci;
Query OK, 0 rows affected (0.00 sec)

mysql> create table surname(surname varchar(255) primary key);
Query OK, 0 rows affected (0.07 sec)

mysql> insert into surname values('Рублёв');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> insert into surname values('Рублев');
ERROR 1062 (23000): Duplicate entry 'Рублев' for key 'PRIMARY'

Я придумал только один способ, исправляющий это поведение (но у него есть недостаток):

mysql> create table surname(surname varchar(255) primary key collate 'utf8_bin');
Query OK, 0 rows affected (0.02 sec)

mysql> insert into surname values('Рублёв');
Query OK, 1 row affected (0.00 sec)

mysql> insert into surname values('Рублев');
Query OK, 1 row affected (0.00 sec)

mysql> select * from surname where surname='рублев';
Empty set (0.00 sec)

Я выключил case insensitive у данного столбца, явным указанием «collate». Это полностью решает проблему с «ё», но лишает нас удовольствия искать, не заботясь о совпадении регистра.

18 комментариев

Нужен сисадмин и разработчик на Пайтон

Привет!

Мне в группу внутренних сервисов компании «Яндекс» нужен разработчик на Пайтон. Так же ребята из группы администрирования попросили написать, что нам нужен системный администратор (Linux).

Пишите либо в комментарии, либо на почту (bolk@yandex-team.ru), отвечу на интересующие вопросы. У нас очень хорошие условия работы!

12 комментариев

Небольшая задача на Пайтоне

Вот вам небольшая задача на Пайтоне, для того, чтобы понять как у вас с функциональным программированием. Выполнить надо в уме (я смог, значит это возможно). Что вернёт следующее выражение:

(lambda x:x(x))(lambda z: lambda y:z)(1)(2)(3)

Добавлено позднее: если кому-то проще JavaScript, вот тот же код на JavaScript 1.8:

(function (x) x(x))(function (z) function (y) z)(1)(2)(3)

16 комментариев

Невероятный JavaScript

Насколько запутанный JavaScript вы можете написать? Хотя JS-игра, которую мы сокращали на пару с LO, выглядит довольно запутанно, но можно писать куда более непонятно, если ваша цель не сократить объём, а сделать так, чтобы у читающих листинг вашего кода выпали глаза.

В блоге Shadowflux образчик хорошо запутанного кода с объяснением работы:

($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+
($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__
[_+~$]+$_[_]+$$](_/_)

Выглядит довольно страшно, но, если разобраться, ничего сложного. Напоминает старый добрый Perl.

7 комментариев

Антиалиасинг шрифтов: кто прав, Microsoft или Apple (ответ — никто)

На «Хабре» перевод статьи «Разоблачение алгоритмов растеризации шрифтов» (в двух частях).

Рассматриваются различные алгоритмы растеризации шрифтов и очень интересные проблемы.

Кстати, в статье есть ответ почему текст в Linux смотрится так плохо.

21 комментарий

Как сэкономить один байт в GIF

Trailer (7.79КиБ)

Я понимаю, один байт — не бог весть что, но, возможно, кому-то и такая мелочь будет приятна. Например, полезно во всяких конкурсах, вроде JS1K и т. п.

Файл в формате GIF должен заканчиваться символом с кодом 0x3B («;»), который называется «trailer». На самом деле, этот символ чаще всего не требуется декодерами (хотя обязателен в стандарте). Я проверил на сервисе скриншотов, все браузеры, которые там перечислены, кроме Konqueror 4.2 и выше, поддерживают файлы GIF без этого байта.

Я так же вывесил такой GIF у себя на сайте, обнаружилось, что его так же не поняли агенты, которые подписываются как Java/1.6.0_xx (думаю, это какие-то браузеры на J2ME).

Вывод: если вас это не смущает, то можете сократить свои GIFы на один байт. Или, напротив, проверьте имеют ли ваши GIF этот байт, если для вас почему-то важны эти браузеры (основанные на J2ME и Konqueror 4.xx).

4 комментария

Internet Explorer показывает не все GIF

Скриншот кода с ошибкой 56: «Смысл не найден» после команды «0109 повтор», имитирующей бесконечный цикл жизни.
IE, не покажи этот GIF!

Нашёл в ЖЖ DiBR’а GIF, который не показывает Internet Explorer. Забавно, хотя в отличие от JPEG, который не показывает современная «Опера», этот GIF несколько некорректен.

Вот текст комментария из ЖЖ, который разъясняет принцип:

Согласно описанию формата, сразу за заголовком («GIF89a») идет Logical Screen Descriptor (в котором как раз и прописан размер 80×80), затем Global Color Table, а уж за ним — всякие Extensions и данные изображений. В обсуждаемом файле Global Color Table просто отсутствует (так что IE ведет себя вполне адекватно). Зато присутствует картинка размером 100×100, которую и видят менее привередливые рендереры.

Оставить комментарий

Конструкцию «with» убрали в strict mode в ECMAScript 5?

with(){} statements are dead when strict mode is enabled — in fact it even appears as a syntax error. While the feature was certainly mis-understood and possibly mis-used I’m not convinced that it’s enough to be stricken from the record.

Я, конечно, понимаю чем плоха конструкция with, но отключать её в strict mode… Мне кажется излишним.

ECMAScript 5, кстати, будет в FireFox 4.

6 комментариев

MakeCorner shell

MC Shell (31.42КиБ)

Хочу порекламировать MC Shell — графическую оболочку для моего консольного скруглятора картинок, которую пишет oldTV, в архив программы уже входит моя утилита, так что ничего дополнительно качать не нужно.

30 комментариев

Сериал для программистов на JavaScript

Не пропустите новогодний сериал для программистов — мы с неким LO сокращаем мой второй вариант игры «Tank 1K», написанный по рождественским правилам конкурса JS1K (программ на JavaScript, умещающихся в 1КБ).

Уже сократили с 1023 до 773 770 759 752 723 байта (более чем на 29% и это на таком крошечном размере).

Для меня — полезное соревнование, тренинг, о котором только можно мечтать, у LO отлично варит голова. Для вас — возможность посмотреть как в JS можно сократить размер программы. Уже сейчас видно, что из некоторых ходов вполне можно вывести правила, например: «если у тебя в программе есть пустые скобки любого вида, посмотри нельзя ли их чем-нибудь занять».

Если какие-то места программы непонятны, можно смело спрашивать тут, в комментариях.

3 комментария

«Опера» 9.50 и выше показывает не все JPEG

«Опера», не покажи этот JPEG! (11.92КиБ)

Случайно выяснилось, что «Опера» с какой-то версии не умеет показывать некоторые JPEG (и считает, что в них 0 бит на пиксель). Попытаюсь выяснить с какой версии это началось.

Добавлено: «Опера» 9.00, 9.27, 9.63, 10.00, 11.00, 11.01а и Opera Mini 5.1 не показывает. «Опера» 8.54 — показывает. Значит сломали в девятой версии.

23 комментария

Расширение для «Оперы»: сайт только у меня не видно?

Артемий Трегубенко написал расширение для «Оперы» «У всех работает».

У всех работает? (44.87КиБ)

Смысл в том, что если ваша «Опера» показывает экран с ошибкой «Невозможно найти удалённый сервер», это расширение при помощи сервиса «Down for everyone or just me» проверяет доступность того же сайта для других пользователей.

Полезно, можно узнать проблема с сайтом или у вашего провайдера.

А картинка, которая в этом посте, только в моей «Опере» не показывается или в вашей тоже?

Добавлено: картинка не открывается под любой платформой в последней «Опере», сейчас потестирую в других.

Чуть позже: «Опера» 8.54 показывает, 9.63 — уже нет. Я заменил картинку на такую, которую «Опера» понимает.

7 комментариев

localStorage для Internet Explorer 6 и 7

Написал небольшой класс в JavaScript для поддержки API localStorage в IE 6 и 7. localStorage — это браузерное хранилище key-value. Эмулируются setItem, getItem, removeItem, key, clear и length (для хранения использует behavior userData).

Доступ к значениям как к свойствам класса не реализован. Прежде всего потому, что в JS в этих версиях IE нет сеттеров и геттеров, а для того, чтобы воспользоваться onpropertychange мой объект надо поместить в DOM, что порождает массу гемороя, типа присутствия свойств из DOM, а не из хранилища.

Так же я не сделал события onstorage и onstoragecommit, потому что не придумал для чего это нужно (а второе корректно реализовать вообще нельзя).

Ещё не реализовал нестандартное, но полезное расширение remainingSpace, потому что в общем случае нельзя сказать сколько места ещё осталось в userData, так как квота зависит от зоны сайта (доверенная, интранет и так далее).

С большой вероятностью эта зона, конечно же, «интернет» (то есть квота 1МБ), но квоты localStorage сильно отличаются по механизму от userData, у последнего две квоты — на документ (в зоне «интернет» это 128КБ) и на домен (упомянутый мегабайт). Вполне может случится, что квота «на документ» ещё не исчерпана, а доменная уже да.

Зато я реализовал exception, который бросается в том случае, если IE говорит, что квота исчерпана.

В общем, основные вещи есть. Пример использования:

// .-~*´¨¯¨`*·~-.¸ тут подключаем библиотеку ,.-~*´¨¯¨`*·~-.¸
// записываем два значения
try {
    localStorage.setItem('key1', 'myvalue1');
    localStorage.setItem('key2', 'myvalue2');
} catch (e) {
    if (e.description == 'QUOTA_EXCEEDED_ERR') {
        alert('Нет места');
    } else {
        alert('Что-то не так, не знаю что.');
    }
}

// смотрим значение по ключу «key1»
alert(localStorage.getItem('key1'));
// смотрим первое значение (по номеру), нумерация с нуля
alert(localStorage.key(0));

// удаляем значение по ключу «key1»
alert(localStorage.removeItem('key1'));

// смотрим сколько ключей осталось
alert(localStorage.length);

// очищаем хранилище полностью
alert(localStorage.clear());

6 комментариев

← 1 42 43 44 45 46 67 →