dr.Brain

doctor Brain

мир глазами веб-разработчика

JavaScript: магия чисел

Некоторые особенности работы с числами в JavaScript

dr.Brain

время чтения 4 мин.

Photo by Volcan Olmz on Unsplash

Число (Number) - один из основных типов данных в JavaScript. В компилируемых языках программирования такой тип данных должен называться double или float64. И, как и в других языках программирования, числа имеют определенные максимальные и минимальные значения:

const maxInt = Number.MAX_SAFE_INTEGER // 9007199254740991
const minInt = Number.MIN_SAFE_INTEGER // -9007199254740991

minInt === -maxInt // true

const maxDouble = Number.MAX_VALUE // 1.7976931348623157e+308
const minDouble = Number.MIN_VALUE // -1.7976931348623157e+308

Давайте разберемся: что за странные длинные цифры мы получаем в минимальных и максимальных значениях?

Это первый волшебный способ представления чисел в JavaScript: с помощью основания и экспоненты (beN):

const minusTwo = -2e0 // -2
const one75 = 175e-2 // 1.75

На практике, мы пишем число, которое является основанием, затем пишем e и определаем, куда нужно сместить разделитель десятичных знаков. Если число после e положительное - мы добавляем ноли, если отрицательное - смещаем разделитель влево:

const zero = 0e0 // 0; смещает разделитель относительно 0.0 ноль раз
const zero5 = 5e-1 // 0.5; смещает разделитель относительно 5.0 один раз влево
const fifty = 5e1 // 50; смещает разделитель относительно 5.0 один раз вправо
const alsoFifty = 5e+1 // 50; тоже смещает разделитель относительно 5.0 один раз вправо
const minusFifty = -5e+1 //-50; смещает разделитель относительно -5.0 один раз вправо
const seventeen5 = 1.75e1 // 17.5; смещает разделитель относительно 1.75 один раз вправо

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

const million = 1_000_000; //1000000
const fiveK = 5_000 // 5000
const justLoveUnderscores = 1_2_3.3_2_1 //123.321

const oops = 1__0 // Error: только один знак подчеркивания можно использовать, как разделитель
const nope = 0_1 // Error: разделитель чисел не может применяться после ведущего ноля

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

const five = 0b101 // 5
const alsoFive = 0B101 // 5; `b` не чувствительна к регистру
const max8bit = 0b1111_1111 // 255; Разделитель можно использовать для всех видов чисел :-)
const lessFive = -0b0101 // -5

Конечно, шестнадцатиричные числа hexadecimal должны присутствовать в нашем арсенале:

const max8bit = 0xff // 255
const hexNum = -0xabc // -2748
const max32bit = 0xffff_ffff // 4294967295; также можно использовать разделитель

Следует помнить, что в ECMA Script 2015 есть восьмиричные числа octals:

const maxBit = 0o7 // 7
const eight = 0o10 // 8
const funnyZero = 0O0 // 0

Иногда, может случится так, что необходимое целое числое не уместится в 64 бита. В таком случае его можно сконвертировать в BigInt, добавив суффикс n:

const maxDouble = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // Infinity
const biggerThanMaxDouble = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn // 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215n

const bigTen = 10n // 10n;
const bigLess50 = -50n // -50n

А вот несколько действительно волшебных чисел в JavaScript:

Infinity === Number.POSITIVE_INFINITY // true
-Infinity === Number.NEGATIVE_INFINITY // true
const smallestFraction = Number.EPSILON // 2.2204460492503130808472633361816e-16
smallestFraction === Math.pow(2, -52) // true

У чисел в JavaScript есть “странный родственник” - это специальное значение, которое на самом деле не является числом.

NaN - специальное значение в JavaScript. Любая операция с ним приведет к NaN, даже сравнение:

NaN === Number.NaN // false !!
Number.isNaN(NaN) // true

NaN + 1 // NaN
NaN * 15 // NaN
NaN / NaN // NaN
1 * NaN // NaN

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

parseInt('abc') // NaN
parseInt({}) // NaN
parseFloat('1.1.1') // NaN
'abc' * 1 // NaN
new Number('abc') // Number {NaN}
Math.abs('abc')

Тем не менее, в JavaScript есть встроенные функции, которые позволяют справиться с проблемами приведения типов и NaN:

Number.isNaN(123) // false
Number.isNaN('abc') // true
Number.isNaN(NaN) // true

Number.isFinite(123) // true
Number.isFinite(Infinity) // false
Number.isFinite(NaN) // false

Number.isInteger(123) // true
Number.isSafeInteger(9007199254740992) // true !!
Number.isInteger(12.3) // false
Number.isInteger(Infinity) // false
Number.isInteger(NaN) // false

Number.isSafeInteger(123) // true
Number.isSafeInteger(9007199254740992) // false
Number.isSafeInteger(12.3) // false
Number.isSfeInteger(Infinity) // false
Number.isSafeInteger(NaN) // false

// BigInts не является Integers:
Number.isInteger(1n) // false
Number.isSafeInteger(1n) // false
// Но это число:
Number.isNaN(1n) // false

Хотите узнать больше? Изучайте Лексический синтаксис JavaScript на MDN.


Спасибо за внимание.


По материалам статьи Valeria “How to do magic with Numbers”.

Новые публикации

Далее

Категории

О нас

Frontend & Backend. Статьи, обзоры, заметки, код, уроки.