我使用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
。
JS中的Int类型是否有任何限制?
答案 0 :(得分:3)
此行为高度依赖于您运行此代码的平台。有趣的是,即使浏览器甚至在同一台机器上也很重要。
<script>
document.write(Math.pow(3,40));
</script>
在我的64位计算机上以下是结果:
IE11 :12157665459056928000
FF25 :12157665459056929000
CH31 :12157665459056929000
SAFARI: 12157665459056929000
答案 1 :(得分:3)
52位JavaScript的64位双精度数值用于存储数字的“分数”部分(执行计算的主要部分),而11位用于存储“指数”(基本上,小数点的位置),第64位用于符号。 (更新:请参阅此插图:http://en.wikipedia.org/wiki/File:IEEE_754_Double_Floating_Point_Format.svg)
在3^40
的基础扩展中有大约63位有效数字(连续意义上为63.3985 ......在离散意义上为64),因此无法准确在JavaScript中使用Math.pow(3, 40)
计算。只有在其基数为2的扩展中具有52或更少有效数字的数字(以及对其在11位内的数量级的类似限制)才有机会通过双精度浮点值准确表示。
请注意,数字的大小与在基数2中使用多少有效数字无关紧要。有许多数字大于或大于3^40
,可以通过JavaScript的64位双精度数值精确表示。
注意:
3^40 = 1010100010111000101101000101001000101001000111111110100000100001
(基数为二)
(以1开头和结尾的最大子串的长度是基数为2的有效数字,在这种情况下是64位数的整个字符串。)
答案 2 :(得分:1)
JavaScript只能代表 distinct 整数to 253(或~16位有效数字)。这是因为所有 JavaScript数字的内部表示形式为IEEE-754 base-2 double。
因此,Math.pow
的结果(即使 内部准确)是残酷的“舍入”,结果仍然是JavaScript整数(因为它被定义为返回每个规范的整数) - 结果数字因此不正确的值,但JavaScript可以处理的最接近整数近似值。
我已将下划线放在数字之上,而这些数字并未[完全]使“有效数字”截止,因此可以看出这会对结果产生怎样的影响。
................____
12157665459056928801 - correct value
12157665459056929000 - closest JavaScript integer
另一种看到这种情况的方法是运行以下命令(结果为true):
12157665459056928801 == 12157665459056929000
来自规范中的The Number Type部分:
请注意,数量类型不超过2 53 的所有正整数和负整数都可以在数字类型中表示。
..但并非所有具有大幅度的整数都是可表示的。
在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"
答案 3 :(得分: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)进行计算。
答案 4 :(得分:0)
不能说我肯定知道,但这看起来像是一个范围问题。
我认为数学库通常使用对数来实现取幂。这要求两个值都变成浮点数,因此结果在技术上也是浮点数。当我要求MySQL进行相同的计算时,这是最有说服力的:
> select pow(3, 40);
+-----------------------+
| pow(3, 40) |
+-----------------------+
| 1.2157665459056929e19 |
+-----------------------+
你实际上回到一个大整数可能是礼貌的。