Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как получить максимальное и минимальное допустимое число в не экспоненциальном виде? (https://javascript.ru/forum/misc/15299-kak-poluchit-maksimalnoe-i-minimalnoe-dopustimoe-chislo-v-ne-ehksponencialnom-vide.html)

FINoM 21.02.2011 05:39

Как получить максимальное и минимальное допустимое число в не экспоненциальном виде?
 
Сабж.

monolithed 21.02.2011 09:37

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());

FINoM 23.02.2011 04:53

Спасибо, но я ничего не понял :)
Регулярки, тернарные операции... А уж тем более то, что вы привели вконце: зачем мне строка с цифрами, полученная в результате возведения в степень, если мне просто нужно самое большое число типа Number в "точном" виде. А для чисел бОльших, чем сабж можно использовать bigInt.

monolithed 23.02.2011 10:57

Цитата:

Сообщение от FINoM
но я ничего не понял

продолжайте учить язык, что тут сказать ;)
Цитата:

Сообщение от FINoM
А уж тем более то, что вы привели вконце: зачем мне строка с цифрами, полученная в результате возведения в степень

можете убрать возведение в степень, зачем это сделано объяснять не буду
Цитата:

Сообщение от FINoM
если мне просто нужно самое большое число типа Number в "точном" виде

так оно и есть!
Цитата:

Сообщение от FINoM
А для чисел бОльших, чем сабж можно использовать bigInt.

в ES нет такого типа данных

FINoM 23.02.2011 13:19

Цитата:

Сообщение от monolithed
так оно и есть!

Угу http://my.jetscreenshot.com/demo/20110223-gqhe-50kb.jpg
Цитата:

Сообщение от monolithed
в ES нет такого типа данных

Пардон, библиотеку bigInt.

monolithed 23.02.2011 13:27

Цитата:

Сообщение от FINoM

это сарказм?
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);

Amphiluke 23.02.2011 15:19

Вообще-то, зная формат представления вещественных чисел в памяти, можно получить максимальное и минимальное значения типа 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

Поправьте, если ошибся. :)

B@rmaley.e><e 23.02.2011 17:49

Amphiluke, если не ошиблись с количеством нулей, то похоже на правду. Во всяком случае первые значащие цифры совпадают с тем, что выводит браузер в экспоненциальной записи
alert( Number.MAX_VALUE )

Aetae 23.02.2011 19:43

Забавно всё это)
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'))

Amphiluke 23.02.2011 20:24

Aetae, это тоже можно объяснить, исходя из понятия т.н. «машинного эпсилон». :)

Размер мантиссы для вещественных чисел в Javascript составляет 52 бита. Поэтому наименьшее число, представляющее разницу между двумя возможными значениями мантиссы равно (в двоичной системе)

0.000000000000000000000000000000000000000000000000 0001,

или 2^(-52) = 2.22e-16. То есть как минимум в 17-м знаке после запятой (в десятичной системе счисления) будут наблюдаться погрешности округления. Видимо, для вашего примера, причина в этом.


Часовой пояс GMT +3, время: 01:40.