// codeart.ru / Статьи / Как быстро проверить число на NaN

Как быстро проверить число на NaN

Автор: Evgeny Sergeev

Сегодня копался в коде jQuery и обратил внимание на то каким образом осуществляется проверка числа на NaN. Вместо того, чтобы использовать стандартную функцию isNaN() Johng Resig преобразует число к строке и сравнивает его со строкой ‘NaN’.

Я подумал, что раз используется такой странный способ, то тому есть свое логическое объяснение. Первое, что пришло мне на ум — выигрыш в скорости, но как оказалось это совершенно не так.

Для проверки я написал простенький скрипт:

function a() {         for (var i = 0; i < 100000; i++) {                 var n = parseInt('AAAA');                 isNaN(n); // true         } } function b() {         for (var i = 0; i < 100000; i++) {                 var n = parseInt('AAAA');                 'NaN' == n.toString() ; // true         } } a(); b();

Чтобы не заморачиваться на измерение скорости средствами JavaScript использовал профилирование встроенное в плагин FireBug.

После проведение замеров FireBug показал следующее:

 функция b() - 32 мс
 функция a() - 13 мс.

Получается, что isNaN() работает быстрее более чем в два раза!

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

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

Из сказанного выше, можно сделать вывод, что для работы в FireFox лучше использовать функцию isNaN. Но значит ли, что не существует другого более быстрого способа проверить число на NaN?

Чтобы ответить на данный вопрос, я решил провести еще пару экспериментов.

Первое, что пришло мне на ум — это изменить способ перевода числа в строку, для этого я заменил код n.toString() == ‘NaN’ на n + ” === ’NaN’; в результате функция b(); стала выполняться на 5мс быстрее. Но функция isNaN() все равно работала значительно лучше.

Второе решение, я нашел в интернете и заключается оно в том, чтобы проверить равно ли число само себе, а точнее не равно ли оно само себе:

var n = parseInt('AAAA');  n != n // true

Я уже писал об особенностях числа NaN одно из которых заключается в том, что NaN не равно самому себе, таким образом сравнение n != n будет истинным только в случае когда n равно NaN.

Чтобы проверить указанный метод. Я заменил проверку toString() на n != n и запустил профилирование повторно. В результате были получены следующие значения:

 функция a() - 13 мс
 функция b() - 8 мс (!)

Таким образом, на сегодняшний день самый быстрый способ (известный мне) проверить число на значение NaN — это выполнить проверку n != n.

  1. И для каких задач проверка на NaN настолько критична? Зачем ее “убыстрять”? Тем более для ста тысяч значений. Что 8мс что 32 мс. Какая разница? :)

  2. Михаил, на вопрос “зачем?” каждый должен ответить для себя сам. Кому-то нравится искать самый быстрый способ, кому-то нет - каждому свое.

  3. 2Evgeny Sergeev
    совершенно согласен с Вами! Мне очень нравиться ускорять и без того очень быстрое, находить самые хитрые и блестящие способы решения тех или иных задач.

    Спасибо за статью =)

  4. Илья какой ты ускоритель прям. Да. Соглашусь. Статья хорошая. Присоединяюсь к спасибу!

  5. Михаил, ты не прав, Женя сказал однозначно, если надо, ищем решение, не надо, пишем как получится.
    Например, я знаю фокус с циклом, сильно ускоряет, это тоже не нужно? Сомневаюсь, что кто-то в здравом уме отмахнётся, типа, “да кому это надо”.
    В некоторых случаях очень даже надо.

    Женя, если тебе интересно про циклы, и у меня не получится на тебя выйти, попробуй ты мне написать.

Leave a Reply

« JavaScript. Грабли с NaN Проблемы с PHP DirectoryIterator »