js中最大的数字是多少?
它的值可以通过Number.MAX_VALUE得到,在控制台打印得到值:1.7976931348623157e+308。
但,以为就这样就完了吗?
有没有想过,为什么是这个值呢?而js最大安全整数又是多少,最大位运算又是多少,为什么有个安全数的说法,为什么0.1+0.1 ==0.2为true,0.1+0.2 ==0.3为false,这是js的问题吗?无法精确表示,那在编程中如何解决呢?具体到实际开发中表现出的问题java的long不能用javascript的number表示出上限,如何解决?
简单的一个问题,但追根溯源中发现牵扯很多的知识点。别急,我们一个个来说明白。
和某些编程语言(如C和Java)不同,javascript不区分整数值和浮点数值,所以我们看到js中数字没有int,short,long,float这些区别。换言之,它也没法区分1和1.0。js中所有数字均用浮点数值表示,它采用IEEE754标准定义的64位浮点格式表示数字,这种格式就像java,c中的双精度(double,双精度浮点数)类型一样。
双精度浮点数(double)是计算机使用的一种数据类型,它使用 64 位(8字节)来存储一个浮点数,格式如下:
- sign bit(符号): 用来表示正负号,占1位
- exponent(指数): 用来表示次方数,占11位
- mantissa(尾数): 用来表示精确度,占52位
参考资料:维基百科双精度浮点数
我们知道, 任何一个二进制浮点数可以如下表示:
参考资料:https://www.zhihu.com/question/24423421
因为1<=M<=2,也就是M可以写成1.xxxx的形式,xxxx表示小数位,mantissa保存的就是小数部分。指数位有11位,因为指数可正可负,所以它可以表示的范围是-(2的11次方)/2 ~ ((2的11次方)/2-1),也就是-1024~1023。所以有,可以表示的最大值为1.11111(52个1)乘以2的1023。这个值,也就是 JavaScript 中的 Number.MAX_VALUE: 1.7976931348623157e+308。
js权威指南3.1指出:按照js中的数字格式,能够表示的整数范围是从−9007199254740992 ~ 9007199254740992(即正负2的53次方),包含边界值。如果使用了超过此范围的整数,则无法保证计算精度。某些操作(如数组索引还有位操作)是按32位处理的.
例如:
var a = 9007199254740992;
console.log(a+3);
正确的运算结果应该是9007199254740995,但JavaScript给出的计算结果却是9007199254740996。尝试改变计算公式后可以发现,只要整数大于9007199254740992,这种计算结果的错误将频繁出现。如果说计算精度的偏差尚可接受的话,在循环中使用了超过此范围的数字还会导致死循环,这就不是小问题了。
因为计算精度,我们知道有了安全数的说法,而也是因为精度缘故,所以有0.1+0.1 ==0.2为true,0.1+0.2 ==0.3为false的问题,可以在控制台输出验证看看结果。这个问题,也是精度导致的,但这是浮点数的精度问题导致。所以,这个问题不仅仅用js会得到这个结果,用别的编程语言来计算这样的浮点数运算也会得到同样的结果。
解决办法:
- 尽量不用浮点数,js中因为都是浮点数这个方法对它不行。
- 浮点数定点化。
- 用字符串表示数字。
- 用数组表示大数解决大数过大时的精度问题。
一般用字符串来解决这个问题,如@sumory提到,开发中遇到过这个问题,由Java的64位的long型传到页面再传到后台使用,结果达到上限了,java的long不能用javascript的number表示出上限,需要用string代替来传值,否则会丧失精度。
参考资料: