Blog. Just Blog

Методы parseInt и parseFloat: особенности и альтернативы

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
Для преобразования строки в число в JavaScript используются два метода: parseInt - для целых чисел и parseFloat для чисел с плавающей запятой. В официальной документации про parseInt сказано примерно следующее:


Метод parseInt возвращает целое значение, равное числу, содержащемуся в его параметре. Если параметр не может быть обработан как целое, возвращается NaN.


И почти то же самое про parseFloat:


Метод parseFloat возвращает числовое значение, содержащееся в его параметре. Если параметр не может быть обработан как число с плавающей точкой, возвращается значение NaN.


Вроде бы все логично и понятно. Еще небольшое отличие, что parseInt имеет второй параметр - основание системы счисления, в которой рассматривается конвертируемое число, к нему мы вернемся чуть позже. А теперь от красивой теории перейдем к суровой практике.

Тепличные условия рассматривать не будем, сразу возьмем какую-нибудь корявую тестовую строку, например, "1234.56fuck":
  1. var "1234.56fuck";
  2. alert (parseInt(a));
  3. alert (parseFloat(a));
Первый раз получаем сообщение 1234, второй раз 1234.56. Я, конечно, могу ошибаться, но по моему разумению строка из этого примера числом не является. Вообще не является. PHP, к примеру, при попытке превратить такую строку в число, однозначно вернет ноль или false. Не знаю, чем руководствовались разработчики JavaScript, но обе функции обрабатывают строку до первого символа, который они не могут распознать в качестве цифры, пробела или разделителя десятичной дроби, и такое поведение также описано в документации. Значение NaN возвращается только в случае, если первый же символ строки не является пробелом или цифрой. Чем это может грозить? Ситуация: на клиентской стороне средствами JavaScript выполняются некоторые проверки или вычисления, основанные на данных, введенных вручную пользователем. Полученные расчетные и введенные данные передаются на сервер и там обрабатываются серверными языками. При ошибке или намеренном искажении ввода могут получиться разногласия с ожидаемыми результатами. Лично я считаю, что любое не-число должно обрабатываться именно как не-число, без вариантов. Для приведения строки к числовому виду я использую такой нехитрый трюк:
  1. var '12345.67';
  2. alert (a-0);
  3. var '12345.67fuck';
  4. alert (a-0);
В первом случае мы получим ожидаемое 12345.67, а во втором - NaN, как и должно быть. Вместо вычитания нуля можно умножать на 1, результат будет тот же самый. Почему нельзя прибавлять ноль? Потому что он будет просто дописан как символ '0' в конец строки. Более универсальная функция для преобразования строки в число будет выглядеть так:
  1. function StrToNum(a) {
  2.   return (a-0);
  3. }
Плюсы этого способа: работает как с целыми, так и с дробными числами, точно определяет не-числа. Возможный минус: обрабатываются только десятичные и шестнадцатеричные числа, другие системы счисления не поддерживаются.

Переходим ко второй части Марлезонского балета. Попробуйте выполнить следующий пример сперва в уме, а затем в браузере:
  1. var '00012';
  2. var '00008';
  3. alert (parseInt(a) + parseInt(b));
Ожидаете, что в сумме получится 20? Однако это не так. Результат этого сложения будет 10. Давайте разберемся, почему так происходит. Если не указана система счисления для конвертирования (второй параметр вызова - radix), то принимаются следующие умолчания: если строка начинается с "0х", то radix = 16; если строка начинается с "0", то radix = 8; в остальных случаях radix = 10. Из-за этого строка '00012' подразумевается записанной в восьмеричной системе счисления и преобразуется в десятичное 10, а строка '00008' преобразуется в 0, потому что цифры 8 в восьмеричной системе счисления вообще нет. Чтобы избежать подобной путаницы, надо всегда явно указывать основание системы счисления в вызове parseInt, но краткий экскурс по Google Code наглядно показывает, что это делается далеко не всеми разработчиками. Альтернативное решение - пользоваться указанной выше функцией StrToNum:
  1. var '00012';
  2. var '00008';
  3. alert (StrToNum(a) + StrToNum(b));
Вот теперь в результате получаем 20. Метод с вычитанием кроссбраузерный, работает надежно и без ошибок. Так что свой выбор я уже сделал.

Поделиться ссылкой ВКонтакте
Просмотров: 13470 | Комментариев: 6

Метки: JavaScript
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
AlexNZ (28.05.2010 в 13:33):
"Не знаю, чем руководствовались разработчики JavaScript..."
Javascript является подмножеством ECMAscript. Стандартами этого языка и пользовались разработчики Javascript.
ManHunter (31.03.2010 в 13:36):
А если я введу какое-то значение с клавиатуры на запрос скрипта? Переменные в примерах инициализированы только для наглядности. В реальном коде такой херни конечно не будет, все числовые переменные я всегда инициализирую как числовые.
64-ядерный процессор (31.03.2010 в 12:27):
Вот код:
var a = 1234.56;
alert (parseInt(a));
alert (parseFloat(a));
Потому, что если нам нужно указать числовое значение, то кавычки не нужны. А если Мы напишем var a = "1234.56fuck"; или var a = '1234.56fuck'; то эта переменная будет восприниматься как текст.
А если мы укажем var a = 1234.56fuck; то JS выдаст ошибку.
Infocatcher (28.03.2010 в 03:29):
С правильными руководствами вообще плохо - или поди пойми, какое правильное, или уже не надо. :)

А parseInt и parseFloat, пожалуй, полезны только для заведомо "хвостатых" строк типа "10px", например.

А заговор - вот тут:
[] == ![] // true
Найдено здесь: http://javascript.ru/forum/off...n-kills.html
ManHunter (28.03.2010 в 00:34):
Только во всех руководствах для преобразования строки в число рекомендуют использовать именно parseInt и parseFloat. И по поводу неявного приведения поведение интерпретатора отличается в случае, например, вычитания и сложения. '123'+3 даст строковую '1233', но '123'-3 даст 120. Так что кругом заговор и неоднозначность :)
Infocatcher (28.03.2010 в 00:17):
По идее, для преобразования (все же "parse" - это не "преобразовать") предполагается использование функции Number:
Number("010"); // 10
Number("10qwe"); // NaN

По все той же идее для неявного приведения типов, когда строка используется в числовом контексте, интерпретатор должен делать то же самое, что и Number().

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.006 сек.) / Память: 4.5 Mb
Наверх