1

首先,我们看下面的代码:

result = 0.1 + 0.2;     
alert(result===0.3);// false
result=100.1+100.2;
alert(result===200.3);//true

我相信0.1100.1(100+0.1) 类似地存储在内存中,因为小数点.1在它们两者中。

那么,为什么加法的结果不同呢?

4

3 回答 3

6

它们在内存中的存储方式不同:http: //steve.hollasch.net/cgindex/coding/ieeefloat.html

0.1 二进制:

0.1 * 2 = 0 + 0.2
0.2 * 2 = 0 + 0.4
0.4 * 2 = 0 + 0.8
0.8 * 2 = 1 + 0.6
0.6 * 2 = 1 + 0.2
0.2 * 2 = 0 + 0.4
0.4 * 2 = 0 + 0.8
0.8 * 2 = 1 + 0.6
0.6 * 2 = 1 + 0.2

如您所见,在 0.2 重复后,整个模式 (0011) 将继续重复,0.1因此0.0001100110011001100110011... 永远重复

为了在 23 位尾数中表示这一点,我们必须将其左移直到小数点前有 1(在将位左移 4 位并删除小数点前的 1 之后100110011...),然后在第 23 位四舍五入,并且我们得到:10011001100110011001101

因为我们移动了 4 个位置,所以我们的指数是127-4(127 是 32 位偏差)。8 位二进制中的 123 是01111011,剩下的就是符号位,我们知道它是 0,因为 0.1 是一个正数。所以 32 位二进制数的每个分量是:

符号:0
指数:01111011
尾数:10011001100110011001101

0.1 表示为00111101110011001100110011001101浮点数。

转换回来,我们必须将其分解,然后将指数转换回十进制整数 (123)。我们将尾数(前面假设为 1)向右移动(127 - 123 = 4)次并得到 :0.00011001100110011001101101然后我们将其转换回十进制:

0*1/2 + 0*1/4 + 0*1/8 + 1/16 + 1/32 + 0*1/64 + 0*1/128 + 1/256 + 1/512 + 
0 + 1/4096 + 1/8192 + 0 + 1/65536 + 1/131072 + 0 + 1/1048576 + 1/2097152 + 
0 + 1/16777216 + 1/33554432 + 0 + 1/134217728

如果你做数学计算,你会得到更接近 0.100000001 的值,而不是 0.1。那是因为我们在第 23 位四舍五入。0.1 不能以二进制存储,因为它永远重复,所以在第 23 位之后我们有不准确之处。当你对一个数字进行算术运算时,这些不准确的地方就会出现,而且误差会变得更大。

如果你对 100.1 做同样的事情,你会得到:

1100100.0001100110011001100... 永远重复:

右移 6 次,去掉小数点前的 1 到第 23 位:10010000011001100110011

指数为 127+6 = 133 (1000 0101)

符号再次为 0,因此您有:

01000010110010000011001100110011
于 2012-04-10T05:02:36.653 回答
0

这是 IEEE 754维基百科的实现结果。没有办法呈现每个浮点数,并且它存在于遵循 IEEE 754 标准的每种语言中。此代码段在任何语言中都将具有相同的结果:

var sum = 0.0;
for (var i = 0; i < 10; i++ )
{
    sum += 0.1;
}
// sum = 0.9999999999999999

0.1 正是没有确切表示wikipedia的数字之一。

C# 有一个特殊的 Decimal MSDN类型,适用于金融和货币计算,内部是一个结构。

于 2012-04-10T05:59:16.407 回答
0

除了 Paul PRO 的回答

这不仅仅是 javascript 的问题。在 C# 中 double 表现出相同的行为

double a = 0.1, b = 0.2;
Console.WriteLine((a + b)==0.3); //Prints False

因此,建议在 c# 中使用小数来提高精度。对于 javascript,您应该使用 .toFixed 来处理货币操作。有关 javascript 中数字的更多信息,请查看http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference#quickIDX0

于 2012-04-10T05:20:42.227 回答