JavaScript много лет остаётся самым используемым языком программирования для веба. Он работает в браузерах и на серверах, обеспечивает интерактивность веб-страниц и работу приложений в реальном времени. Но когда дело доходит до чисел, JavaScript может удивить. Сегодня рассмотрим несколько таких ситуаций. А для затравки — тот самый мем, который когда-то разошёлся по соцсетям:
Если число состоит из цифр от ноля до семи, но в начале стоит ноль
Представим, что мы сравниваем числа с помощью JavaScript. Возьмём пример из картинки выше и на всякий случай напомним, что для сравнения JavaScript приводит обе стороны равенства к одному типу:
console.log(018 == '018')
console.log(018 == '017')
Кажется, что результат сравнения должен быть одинаковым, но в первом случае мы получим True, а во втором — False:
Давайте разбираться, в чём тут дело. Если число начинается с 0, JavaScript предполагает, что оно написано в восьмеричном формате, и выполняет необходимые преобразования. На первый взгляд это хорошо, но на практике появляются противоречия.
В примере выше 018
— недопустимое восьмеричное число. Восьмеричная система счисления допускает использование только восьми цифр от 0 до 7. Но раз в числе 018
есть восьмёрка, то JavaScript теперь рассматривает его как обычное десятичное, то есть равное 18. Когда это число анализируется как десятичное, получается, что '018' = 18
— и выражение является истинным.
При этом 017
— допустимое восьмеричное число. Вот только JavaScript представляет его внутренне как 15, потому что 1×8¹ + 7×8⁰ = 15. А строку '017'
он рассматривает как десятичное число, в результате чего получается 17. Но 15 не равно 17, поэтому второе выражение неверно.
Убедимся в этом на практике:
Если число начинается с ноля, за которым идёт буква b
Если после ноля в числе идёт буква b, а дальше снова цифры, то это — число в двоичной системе счисления. Там могут использоваться только 0 и 1, поэтому числа в двоичной системе в JavaScript выглядят так:
0b0110011
Символ b — это сокращение от binary, что переводится как «двоичный». Встретив такое написание, JavaScript поймёт, что перед ним число в двоичной системе счисления, и переведёт его в обычное десятичное число:
При этом, если мы захотим сравнить его со строкой, то здесь тоже не будет проблем:
И даже если мы в строке напишем десятичное число 51, то при сравнении тоже не получим ошибки:
Если число начинается с ноля, за которым идёт буква x
Если b означает двоичную систему счисления, то x — шестнадцатеричную. Это значит, что в основании такой системы счисления лежит число 16 (а в десятичной — 10). Но в записи числа один символ должен означать одну цифру, а односимвольных цифр у нас всего десять, от 0 до 9.
Чтобы решить эту проблему, программисты договорились обозначать цифры буквами:
A = 10
B = 11
C = 12
D = 13
E = 14
F = 15
Получается, что если JavaScript встретит число 0x21AF, то он может перевести его в десятичный формат и получить число 8623: 2×16³ + 1×16² + 10×16¹ + 15×16⁰ = 8623
Вывод и сравнения работают точно так же, как и с числами в двоичной системе счисления:
И зачем мне это знать?
Знание того, как JavaScript работает с разными форматами чисел в зависимости от представления, может помочь не допустить ошибок в проектах или найти их там, где они уже есть. А ещё этим можно похвастаться перед знакомыми программистами — уверены, часть из них с таким ещё не встречались.