Как получить максимальное и минимальное допустимое число в не экспоненциальном виде?
Сабж.
|
Number.prototype.toDigits = function() { var str = this.toString(), tmp = '', i, d, x = str.match(/^(\d+)\.(\d+)[eE]([-+]?)(\d+)$/); if(x) { d = x[2]; i = (x[3] == '-') ? x[4]-1 : x[4]-d.length; while(i--) { tmp += '0'; } if(x[3] == '-') { return '0.'+tmp+x[1]+d; } return x[1]+d+tmp; } return str; }; alert(Math.max(Math.pow(2147483648, 2), Math.pow(2147483648, 3)).toDigits()); |
Спасибо, но я ничего не понял :)
Регулярки, тернарные операции... А уж тем более то, что вы привели вконце: зачем мне строка с цифрами, полученная в результате возведения в степень, если мне просто нужно самое большое число типа Number в "точном" виде. А для чисел бОльших, чем сабж можно использовать bigInt. |
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
|
Цитата:
Number.prototype.toDigits = function() { var str = this.toString(), tmp = '', i, d, x = str.match(/^(\d+)\.(\d+)[eE]([-+]?)(\d+)$/); if(x) { d = x[2]; i = (x[3] == '-') ? x[4]-1 : x[4]-d.length; while(i--) { tmp += '0'; } if(x[3] == '-') { return '0.'+tmp+x[1]+d; } return x[1]+d+tmp; } return str; }; function intSize() { var arg = arguments, i = arg.length, array = []; while(i--) { array.push(arg[i]); } alert('Min: '+Math.min.apply(null, array).toDigits()+ '\nMax: '+Math.max.apply(null, array).toDigits()) }; intSize(1147483648000000000000000, 2147483648000000000000000, 3147483648000000000000000); |
Вообще-то, зная формат представления вещественных чисел в памяти, можно получить максимальное и минимальное значения типа Number без привлечения Javascript-программы.
Например, мы знаем, что в памяти под число вещественного типа комп отводит 8 байт, из которых 52 бита занимает мантисса, 11 бит — экспонента и один знаковый бит. В этом случае максимальное значение вещественного числа в двоичной нотации должно выглядеть так: 01111111 11101111 11111111 11111111 11111111 11111111 11111111 11111111 Последний, старший разряд (выделен голубым) равен 0, т.е. число положительное. 11 бит экспоненты выделены красным, а мантисса — зеленым. Взять все единицы в экспоненте нельзя, т.к. такое значение экспоненты зарезервировано под значения Infinity или NaN. Поэтому младший разряд оставлен нулевым. Чтобы получить истинное значение мантиссы, к ней нужно добавить единицу с разделительной точкой, т.е. в этом примере мантисса реально равна числу в двоичной записи 1.1111 11111111 11111111 11111111 11111111 11111111 11111111 В десятичной записи это число практически равно двойке, а точнее можно вычислить при помощи формулы для суммы n=52 членов геометрической прогрессии со знаменателем 0.5. Наше двоичное число в переводе в десятичную систему равно 1 + 1/2 + 1/4 + 1/8 + 1/16 + ... + 1/2^52 = 1 + 0.5 · (0.5^52 - 1)/(0.5 - 1) = 1.99999999999999977795539507496869... Мантиссу нашли, теперь ее надо умножить на экспоненту. При расчете экспоненты за ноль принимается число 1023. Наша экспонента в двоичной записи равна 11111111110, что в десятичной эквивалентно числу 2046. Поскольку за ноль принято 1023, то реально экспонента равна 2046-1023=1023. Тогда значение, на которое нужно умножить мантиссу равно 2^1023 = 8.9884656743115795386465259539451e+307. В результате максимальное допустимое типом Number число равно 1.99999999999999977795539507496869 · 8.9884656743115795386465259539451e+307 = 1.7976931348623157081452742373164e+308 Далее в спецификации или опытным путем находим, какое максимально возможное количество значащих цифр поддерживает язык при выводе на экран. Пусть это будет 21. Соответственно урезаем найденное максимально возможное число до 22-23 значащих цифр, дописываем в конец оставшиеся нолики и говорим, что получена запись максимального значения с максимально допустимой языком точностью. :lol: 17976931348623157081450000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000 000000000 Поправьте, если ошибся. :) |
Amphiluke, если не ошиблись с количеством нулей, то похоже на правду. Во всяком случае первые значащие цифры совпадают с тем, что выводит браузер в экспоненциальной записи
alert( Number.MAX_VALUE ) |
Забавно всё это)
alert([ Number.MAX_VALUE/(1e293), Number.MAX_VALUE/(1e292), Number.MAX_VALUE/(1e291), Number.MAX_VALUE/(1e290), Number.MAX_VALUE/(1e289), Number.MAX_VALUE/(1e288), Number.MAX_VALUE/(1e287) ].join('\n')) |
Aetae, это тоже можно объяснить, исходя из понятия т.н. «машинного эпсилон». :)
Размер мантиссы для вещественных чисел в Javascript составляет 52 бита. Поэтому наименьшее число, представляющее разницу между двумя возможными значениями мантиссы равно (в двоичной системе) 0.000000000000000000000000000000000000000000000000 0001, или 2^(-52) = 2.22e-16. То есть как минимум в 17-м знаке после запятой (в десятичной системе счисления) будут наблюдаться погрешности округления. Видимо, для вашего примера, причина в этом. |
Часовой пояс GMT +3, время: 22:31. |