В этой статье мы попытаемся понять, как числа хранятся в JavaScript. Как и любой другой язык программирования, все данные хранятся внутри компьютера в виде двоичных чисел 0 и 1. Поскольку компьютеры могут понимать и обрабатывать данные только в виде 0 и 1.
В JavaScript обычно существует только число как примитивный тип данных, но числа имеют форму целого числа и числа с плавающей запятой. Таким образом, эти типы относятся к типу данных Number и хранятся внутри в соответствии с их различными форматами в зависимости от типа выполняемой над ними операции.
Давайте теперь разберемся, как разные числа хранятся в JavaScript.
Хранение целых чисел
Целое число: эти числа далее делятся на два типа.
- Целые числа со знаком
- Беззнаковые целые числа.
Для хранения целых чисел без знака используется простой двоичный формат.
Ниже приведены несколько примеров того, как различные целые числа без знака хранятся в JavaScript.
var a = 4 var b = 78 a will be stored in the memory with the value of:- 100 b will be stored in the memory with the value of:- 1001110
Примечание. Этот метод не работает при работе с целыми числами без знака, поскольку для хранения знака числа требуются дополнительные данные.
Существует соглашение хранить крайний левый бит как бит знака и использовать 0 для положительного и 1 для отрицательного числа.
Этот метод известен как величина со знаком
В приведенном ниже примере показано, как мы будем хранить число в формате Signed Magnitude.
var a = 6 var b = -6 a will be stored in memory with the value of :- 000110 b will be stored in memory with the value of :- 100110
Проблема возникает, когда мы пытаемся выполнить сложение этих двух значений. сложение, выполненное над двоичными числами, возвращает
100110 + 000110 = 101100 // 44
Мы должны получить 0, когда складываем два числа, но вместо этого мы получаем 44.
Было реализовано дальнейшее усовершенствование этого метода, и для хранения числа использовалось представление дополнения до единицы.
Дополнение числа до единицы переключает все 0 в 1 и 1 в 0. Предположим, что существует двоичное число 11001001, тогда его дополнение до единицы будет 00110110.
Теперь давайте разберемся, как этот метод используется для хранения чисел в памяти.
Предположим, что число в двоичном формате равно 100111, что будет рассматриваться как отрицательное число, поскольку 1 — это самый левый бит. Теперь его дополнение равно 011000, что равно 24 в десятичном формате, поэтому мы будем рассматривать 100111 как −24.
В этом методе проблема, возникшая в предыдущем методе, частично решена, так как сложение теперь начинает давать правильные результаты, но все еще есть некоторые исключения, например, когда мы складываем 3 и −2, используя это представление, мы получаем неправильный результат.
3 -> 000011 -2-> 111101 After addition we get -> 000000 which is +0
Ожидалось, что результат будет 1.
Для дальнейшего улучшения этого подхода был введен формат дополнения до двух чисел.
Дополнение числа до двух аналогично дополнению до единицы с одним дополнительным шагом, который после нахождения дополнения до единицы числа 1 снова добавляется к результату.
Два дополнения в предыдущем из 24 ( 011000 ) будут 101000. Это число при добавлении к исходному числу 24 мы получаем 000000 в качестве вывода, где бит переноса игнорируется и арифметическая операция проходит.
24 -> 011000 two's complement of 24 -> 101000 Addition gives -> 1000000 // One is ignored as digits upto 6 bits are counted
Таким образом, −24 будет храниться в памяти как 101000.
Заключение:
При сохранении целых чисел в битах без знака используется простой двоичный формат.
Чтобы хранить битовые целые числа со знаком, числа внутри будут храниться в виде дополнения до двух, чтобы увеличить емкость памяти и улучшить арифметические вычисления.
Хранение чисел с плавающей запятой.
Чтобы сохранить число с плавающей запятой, мы делим его на три части: знаковый бит, показатель степени и мантисса.
- бит знака: он используется для обозначения знака числа с соглашением как 0 для положительного и 1 для отрицательного.
- экспонента: это разница между реальным двоичным числом и его нормализованной формой.
- мантисса: используется для хранения дробной части нормализованной формы числа с плавающей запятой.
Числа с плавающей запятой, представленные в 32-битном формате, называются одинарной точностью, тогда как числа, представленные в 64-битном формате, называются двойной точностью.
Место для хранения, необходимое для хранения числа в разных форматах:
sign | exponent | mantissa | |
---|---|---|---|
single | 1 bit | 8 bits | 23 bits |
double | 1 bit | 11 bits | 52 bits |
Концепция смещения используется в представлении с плавающей запятой для представления отрицательных чисел вместо дополнения до единицы и до двух. Смещение используется, потому что сравнение становится трудным в случае чисел с плавающей запятой с представлениями дополнения до двух.
Например, обычное 6-битное представление будет следовать за числами от 000000 до 111111, но IEEE предоставил формулу, которая также будет хранить отрицательные числа. Если n — количество битов, формула будет такой.
bias = 2(n-1) - 1 // Here n = 6 therefore bias = 31
Это означает, что в 6-битном представлении мы можем хранить числа от −31 до 32.
Давайте посмотрим, как двоичное число 101.101 будет представлено в экспоненциальной записи.
мы получим 1,01101 * 2 ^ 2
- Здесь бит знакаравен 0 и будет самым левым битом
- Показатель степениравен 2. Он укажет расстояние между исходным двоичным числом и нормализованной формой.
- Мантисса — это дробная часть, которая будет равна 01101.
Хранение иррациональных чисел.
Компьютеры по-прежнему не способны хранить иррациональные числа и манипулировать ими, поэтому их нельзя сохранить.
Как числа хранятся внутри JavaScript:
Теперь давайте разберемся, как JavaScript внутренне управляет хранением чисел. В JavaScript нет отдельного формата для представления целых чисел и чисел с плавающей запятой. Он использует числа для всех типов чисел. Внутри JavaScript каждое число хранится как 64 числа с плавающей запятой. В некоторых случаях для арифметических операций с целыми числами используется формат дополнения до двух.
Проблемы с числами с плавающей запятой в JavaScript
- Числа с плавающей запятой не всегда точны и дают приблизительные результаты.
Пример: В этом примере мы попытаемся понять вышеуказанную проблему.
Javascript
var
x = 0.1;
var
y = 0.2;
console.log(x+y);
Вывод: Здесь вместо реального расчета выдается приблизительный результат для быстрого выполнения
0,30000000000000004
- Плавающие числа дают разные результаты в зависимости от их ассоциативности.
Пример: мы поймем проблему ассоциативности на примере, приведенном ниже.
Javascript
var
x = 0.1;
var
y = 0.2;
var
z = 0.3
console.log((x+y)+z);
console.log(x+(y+z));
Вывод: Поскольку вычисления с плавающей запятой основаны на округлении, результат не всегда будет одинаковым, даже если он должен быть одинаковым в реальных приложениях.
0,6000000000000001
0,6