2013-11-22 2 views
1

Я использовал Math.pow() для вычисления экспоненциального значения в моем проекте.Math.pow() не дает точного ответа

Теперь, для конкретных значений, таких как Math.pow(3,40), он возвращает 12157665459056929000.

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

Затем я попытался пройти цикл до экспоненциального значения:

function calculateExpo(base,power){ 
    base = parseInt(base); 
    power = parseInt(power); 
    var output = 1; 
    gameObj.OutPutString = ''; //base + '^' + power + ' = '; 
    for(var i=0;i<power;i++){ 
     output *= base; 
     gameObj.OutPutString += base + ' x '; 
    } 
    // to remove the last comma 
    gameObj.OutPutString = gameObj.OutPutString.substring(0,gameObj.OutPutString.lastIndexOf('x')); 
    gameObj.OutPutString += ' = ' + output; 
    return output; 
    } 

Это также возвращает 12157665459056929000. Есть ли какие-либо ограничения на тип Int в JS?

+2

Кому нужно определить, является ли этот 'научный калькулятор подлинным или' math.pow'? Попробовали ли вы третий метод? Если есть какой-либо предел, он применяется к результату научного калькулятора, то есть меньшее значение –

+1

В этом случае научный калькулятор правильный. –

+0

@JosephMyers По крайней мере, число нечетное, что намекает на то, что он будет более правильным ... – sashkello

ответ

0

Не могу сказать, что я точно знаю, но это похоже на проблему с диапазоном.

Я считаю, что для библиотек математики для реализации возведения в степень используется логарифмы. Это требует, чтобы оба значения были превращены в поплавки, и, таким образом, результат также является технически плавающим. Это наиболее показательным, когда я спрашиваю MySQL, чтобы сделать то же самое вычисление:

> select pow(3, 40); 
+-----------------------+ 
| pow(3, 40)   | 
+-----------------------+ 
| 1.2157665459056929e19 | 
+-----------------------+ 

Это может быть любезность, что вы фактически получаете назад большое число.

1

JavaScript может представлять только целые числа to 253 (или ~ 16 значащих цифр). Это потому, что все Номера JavaScript имеют внутреннее представление IEEE-754 двухместных номеров-2.

Как следствие, результат от Math.pow (даже если был точным внутренне) жестоко «округленный» таким образом, что результат все равно целому числу JavaScript (как это определенно для возврата целого числа в соответствии со спецификацией) - и результирующее число таким образом не правильное значение, но ближайшая целочисленная его аппроксимация JavaScript может обрабатывать.

Я положил знак подчеркивания над цифрами, которые не [полностью] выполняют отсечку «значимой цифры», чтобы она могла видеть, как это повлияет на результаты.

................____ 
12157665459056928801  - correct value 
12157665459056929000  - closest JavaScript integer 

Другой способ увидеть это, чтобы запустить следующее (что приводит к истинным):

12157665459056928801 == 12157665459056929000 

Из раздела в спецификации The Number Type:

Заметим, что все положительные и отрицательные целые числа, величина которых не превышает 2 являются представителями ntable в типе номера.

.. но не все целые числа с большими величинами представляются.


Единственный способ справиться с этой ситуацией в JavaScript (например, что информация не теряется) заключается в использовании внешнего кодирования чисел и PoW функцию. Есть несколько различных вариантов, упомянутых в https://stackoverflow.com/questions/287744/good-open-source-javascript-math-library-for-floating-point-operations и Is there a decimal math library for JavaScript?

Например, с big.js, код может выглядеть this fiddle:

var z = new Big(3) 
var r = z.pow(40) 
var str = r.toString() 
// str === "12157665459056928801" 
+0

Wow man how many edits? lol, как только я начну читать, он говорит, что было сделано редактирование: D. О, ты снова поедешь –

+0

@ Ханки 웃 Панки Да, мне нужно пойти в классы EAA :( – user2864740

+0

Что такое решение? Что я делаю? – Janak

2

Такое поведение сильно зависит от платформы вы работаете этот код. Интересно, что даже браузер имеет значение даже на одной и той же машине.

<script> 
document.write(Math.pow(3,40)); 
</script> 

На моей 64-битной машине Вот результаты:

IE11: 12157665459056928000

FF25: 12157665459056929000

CH31: 12157665459056929000

SAFARI:12157665459056929000

+0

Это действительно странно, что IE11 1000 выключен .. он * должен * быть последовательным, я думаю. – user2864740

+0

Вы можете попробовать для вашей машины и посмотреть, не отличаются ли они? –

+0

У меня нет IE11, но IE10/Win7/x64 сообщает «12157665459056928000». – user2864740

1

Haskell (GHCi) дает

Prelude> 3^40 
12157665459056928801 

Erlang дает

1> io:format("~f~n", [math:pow(3,40)]). 
12157665459056929000.000000 
2> io:format("~p~n", [crypto:mod_exp(3,40,trunc(math:pow(10,21)))]). 
12157665459056928801 

JavaScript

> Math.pow(3,40) 
    12157665459056929000 

Вы получаете 12157665459056929000, потому что для вычисления используется плавающая точка IEEE. Вы получаете 12157665459056928801, потому что он использует произвольную точность (bignum) для вычисления.

3

52 бит 64-разрядных значений двойной точности JavaScript используются для хранения части «доли» числа (основная часть выполненных вычислений), а 11 бит используются для хранения «экспоненты» (в основном, положение десятичной точки), а для знака используется 64-й бит. (Обновление: см этой иллюстрации: http://en.wikipedia.org/wiki/File:IEEE_754_Double_Floating_Point_Format.svg)

Есть несколько больше, чем 63 бита стоит значащих цифр в базовые два расширении 3^40 (63.3985 ... в непрерывном смысле, и 64 в дискретном смысле), поэтому он не может быть точно рассчитан с использованием Math.pow(3, 40) в JavaScript. Только числа с 52 или менее значащими цифрами в их расширении базы-2 (и аналогичное ограничение по порядку величины, установленного в пределах 11 бит), могут быть представлены точно с помощью значения с плавающей запятой с двойной точностью.

Обратите внимание на то, насколько велика цифра, не имеет значения, сколько значительных цифр используется для представления ее в базе два. Есть много чисел, больших или больших, чем 3^40, которые могут быть представлены точно по 64-битовым значениям с двойной точностью JavaScript.

Примечание:

3^40 = 1010100010111000101101000101001000101001000111111110100000100001 (основание два)

(Длина самой большой подстроки начала и окончание с 1 является количеством базовых два значащих цифр, которые в данном случае является всей строкой из 64 цифр.)

Смежные вопросы