在一个简单的测试中,当我尝试这样做:
var max = Number.MAX_VALUE;
var x = max + 10;
var min = Number.MIN_VALUE;
var y = min / 10;
我发现在Chrome、IE和Firefox中,x
和max
的值相同,所以似乎一些溢出只是固定到了最大值。而y
被固定为0
,因此一些下溢似乎会变成零。
啊,但事实并不是那么简单。并非所有的溢出都会变成Number.MAX_VALUE
,也不是所有的下溢都会变成Number.MIN_VALUE
。如果你这样做:
var max = Number.MAX_VALUE;
var z = max * 2;
然后,z
将变为Infinity
。
事实证明,这取决于溢出/下溢的程度。如果超过了极限,就会得到INFINITY。这是因为使用了IEEE 754四舍五入模式,其中最大值可被视为比无穷大更接近。有关详细信息,请参见添加到Number.MAX_VALUE。根据该答案,1.7976931348623158×10308或更大的值会舍入为无穷大。位于Number.MAX_VALUE和该值之间的值将舍入为Number.MAX_VALUE。
让事情变得更加复杂的是,Javascript还支持逐渐下溢。这是浮点值的尾数中带有前导零的情况。逐渐下溢允许浮点表示一些它不能表示的较小数字,但它们以降低的精度表示。
您可以看到限制在哪里:
>>> Number.MAX_VALUE + 9.979201e291
1.7976931348623157e+308
>>> Number.MAX_VALUE + 9.979202e291
Infinity
这是一个可在任何浏览器中尝试的可运行代码段:
var max = Number.MAX_VALUE;
var x = max + 10;
var min = Number.MIN_VALUE;
var y = min / 10;
var z = max * 2;
document.getElementById("max").innerHTML = max;
document.getElementById("max10").innerHTML = x;
document.getElementById("min").innerHTML = min;
document.getElementById("min10").innerHTML = y;
document.getElementById("times2").innerHTML = z;
body {
font-family: "Courier New";
white-space:nowrap;
}
Number.MAX_VALUE = <span id="max"></span><br>
Number.MAX_VALUE + 10 = <span id="max10"></span><br>
<br>
Number.MIN_VALUE = <span id="min"></span><br>
Number.MIN_VALUE / 10 = <span id="min10"></span><br>
<br>
Number.MAX_VALUE * 2 = <span id="times2"></span><br>
数值
在JavaScript中,数字类型是64位IEEE 754浮点数,不是整数。因此它不遵循其他语言中常见的整数溢出/下溢行为的通用模式。
由于浮点数使用53位进行基本部分表示,所以可以表示范围在Number.MIN_SAFE_INTEGER
到Number.MAX_SAFE_INTEGER
(-253+1到253-1)之间的数字,而不会出现浮点错误。对于超出此范围的数字,可能会被舍入到最近可用的数字,或者如果太大,则可能为Infinity。
位运算符处理操作数32位整数。与其他语言一样,常见的整数溢出可能会发生。计算后只保留最后32位。例如,3<<31
将得到-2147483648
。
>>>
将操作数视为无符号32位整数。所有其他运算符均将操作数视为有符号32位整数。如果要将有符号整数转换为无符号整数,可以编写 value >>> 0
来实现这一点。要转换回,则使用 value | 0
。
如果要将整数向左移动33位,实际上会将其向左移动1位。
BigInt
就像Java的java.math.BigInteger
一样,BigInt
支持无限制的整数(尽管受到内存限制)。因此,在这里可能永远不会发生整数溢出。
对于大多数TypedArray类型,当分配超出支持范围的整数时,它会被截断为其他语言在转换整数时所做的方式,即保留最低有效位。例如,new Int8Array([1000])[0]
得到-24
。
Uint8ClampedArray
与其他TypedArray有些不同。Uint8ClampedArray
支持0~255范围内的整数。使用超出范围的数字时,将设置为0或255。
asm.js
这里应用相同的位运算符规则。值将被截回为| 0
或>>> 0
所执行的内容。
Number.MAX_VALUE * 2
的结果是Infinity
。就像他们说的那样,“想想看”。 - Bernhard Hofmannx
与一个远大于它的数(2^54*x)
相加时,由于四舍五入,小数x
的加法操作会被简单地忽略掉,而乘法操作则总是可以执行的(直到指数溢出)。对于任何对Bernhard结果感到困惑的人来说,这些都是需要注意的。 - HopefullyHelpful1.7976931348623157e+308 + 0.0000000000000001e+308 == Infinity
- Isaac