2013-10-23 38 views
1

我最近发现了一个奇怪的JS代码片段,但是我不确定它是一个bug还是有一些逻辑。Javascript编号获得另一个值

试试这个数字:9000000022903136 * * 警告它,console.log它,将它分配给一个变量。您将获得价值9000000022903136 * *。问题是为什么?它是一个错误?

我也注意到,你从90000000229031352得到​​90000000229031360到90000000229031368,为90000000229031351你90000000229031340,为90000000229031369你90000000229031369.

这发生在:铬,FF,Node.js的

+1

JavaScript的商店*每*号的为内部的浮动,包括整数。你只是失去了精确性。 – Blender

+0

有没有办法避免失去精确度? Java中是否有像BigInteger这样的东西,或者更高精度的东西? –

+0

Google“bigint javascript”。没有内置的东西。 – Blender

回答

3

好,计算机中的数字是有限的(大部分)。你在这里看到的是一个浮点/双重存储号码的经典溢出,它可以保存许多数字,并且它的指数(当然,实际实施方式不同):

123被存储为[1 2 3],指数2 1.23被存储为[1 2 3],指数0

所以,90000000229031368存储为:

[9 0 0 0 0 0 0 0 2 2 9 0 3 1 3 6],指数16.正如你所看到的,最后8位没有空间了,所以当你读时,它被设置为

其他的例子似乎是矛盾的,但请记住,电脑没有存储在基地10这些数字,但基地2

了解更多关于这个问题,关键词是:浮法浮点(例如,在维基百科上)。

+0

谢谢你的好解释,我不知道JS中的整数不是真正的整数。 –

+0

@SilviuBurcea JS中没有整数。有一个Number类型和它的IEEE 64位浮点(通常称为“IEEE double”)。有人建议将真正的整数类型添加到该语言中,或至少是真正的64位整数。 –

3

这是因为javascript数字是64位浮点数。

浮点数有2个部分 - 小数部分定义数字的“值”,指数部分定义数字应该移动到小数点的左边或右边多远。

为了说明这一点的工作,我会使用的十进制基础,而不是二进制的虚浮点数格式如何:

让我们来定义我们想象的格式为8个字符的花车 - 这是数必须存储内8个字符。让分区我们的格式,有6个字符作为小数部分和2个字符作为指数:

_ _ _ _ _ _ _ _ 
    |_ _|_ _ _ _ _ _| <--- 8 char float 
exponent fractional 

为了便于讨论,让我们创造一个语法描述格式:

exponent,fractional 

因此,例如, ,号码128可以存储为0,128,PI可以存储为-5,314159(小数点左移5位)。

上面的PI例子是程序员第一次遇到浮点数 - 他们需要使用分数而不是简单的整数。但是浮点格式还有另外一个特点 - 它可以存储大于分配小数部分空间的数字!

例如,如果我们想要以我们想象的8char浮点格式存储数字987654321会怎么样?它超过6个字符!那么,我们会这样做:2,9876543。也就是说,我们存储最重要的数字并将小数点右移2个空格。

如果我们尝试读取该数字,那么得到的是987654300。我们失去了最低有效位数!嗯..听起来很熟悉。

在javascript的情况下,格式是IEEE 754 64位二进制浮点。它有52位分配给小数部分(如果包含符号位,则为53)。这意味着对于高达52位的数字,它的行为就像一个整数。任何更大的,它将开始牺牲最不重要的位(不是数字,位,所以舍入可能对我们人类看起来很奇怪)。

详情请参见在64位浮点数是如何工作的这个维基百科文章:http://en.wikipedia.org/wiki/Double_precision_floating-point_format