Javascript 为什么具有精确值的浮点数之和仍然取决于顺序?
假设我有3个浮点数,可以用浮点数精确表示:Javascript 为什么具有精确值的浮点数之和仍然取决于顺序?,javascript,floating-point,floating-accuracy,Javascript,Floating Point,Floating Accuracy,假设我有3个浮点数,可以用浮点数精确表示: var a=0.1000000000000000055511151231257827021181583404541015625; var b=0.200000000000000011102230246251565404236316680908203125; var c=0.299999999999999988897769753748434595763683319091796875; 它们是存储在float中的0.1、0.2和0.3的实际值。我认为a+
var a=0.1000000000000000055511151231257827021181583404541015625;
var b=0.200000000000000011102230246251565404236316680908203125;
var c=0.299999999999999988897769753748434595763683319091796875;
它们是存储在float中的0.1、0.2和0.3的实际值。我认为a+b+c应该等于c+b+a,因为a、b和c都已经四舍五入,并且都是精确的值,它们的总和不应该取决于顺序,但现在我测试了它不是:
var a=0.10000000000000055115123125782702118158340454015625;
var b=0.2000000000011102230246256540423631668090908203125;
变量c=0.29999999999988897769753748434595763683319091796875;
console.log(a+b+c==c+b+a)代码>总和不精确
你认为精确值之和是精确的假设是错误的
浮点运算使用固定格式的某些位数(例如24位二进制数字表示浮点
)。两个24位数字的数学和可能有25位,因此需要舍入以表示24位以内(和指数)
此外,当两个指数不同的数字相加时,其中一个数字相对于另一个数字偏移。由于偏移,总和可能有额外的数字,因此必须再次四舍五入
按不同顺序添加数字时,结果舍入可能不同
不精确和的例子
这些示例使用三位二进制有效位
在本例中,加法将带入一个新列:
1.10 • 23
1.01 • 23
――――――――――
10.11 • 23 Exact sum, too many digits, must be rounded.
11.0 • 23 Sum rounded to three digits.
1.10 • 24 Rounded sum, exponent adjusted to normalize significand.
1.10 • 23
1.01 • 23
――――――――――
10.11•23精确和(位数过多)必须四舍五入。
11.0•23和四舍五入为三位数字。
1.10•24四舍五入和,调整指数以规范化有效位。
在此示例中,数字具有不同的指数,为此进行调整会将数字移动到新列中:
1.11 • 23
1.01 • 25 Different exponent requires adjustment.
0.0111 • 25 Adjusted to match exponent.
1.01 • 25
――――――――――――
1.1011 • 25 Exact sum, too many digits, must be rounded.
1.11 • 25 Rounded sum.
1.11 • 23
1.01•25不同的指数需要调整。
调整0.0111•25以匹配指数。
1.01 • 25
――――――――――――
1.1011•25精确和,数字太多,必须四舍五入。
1.11•25四舍五入和。
非结合和的例子
现在,我们可以用不同的方法把三个数字相加,并看到不同的和被产生
我们将比较(1.10•20+1.10•20)+1.00•24)和1.10•20+(1.10•20+1.00•24)
对于第一个表达式,我们添加第一个和第二个操作数,然后添加第三个操作数:
Add first and second operands:
1.10 • 20 First operand.
1.10 • 20 Second operand.
――――――――――
11.00 • 20 Exact sum, too many digits, must be rounded.
11.0 • 20 Rounded sum, must be normalized.
1.10 • 21 Normalized, rounded sum.
Add previous result and third operand:
1.10 • 21 Previous result.
1.00 • 24 Third operand.
Exponents do not match, so adjust and then add:
0.00110 • 24 Previous result adjusted to match exponent.
1.00 • 24 Third operand.
――――――――――――
1.00110 • 24 Exact sum, too many digits, must be rounded.
1.01 • 24 Rounded sum.
添加第一个和第二个操作数:
1.10•20第一个操作数。
1.10•20秒操作数。
――――――――――
11.00•20精确和,数字太多,必须四舍五入。
11.0•20四舍五入和,必须标准化。
1.10•21标准化、四舍五入和。
将上一个结果和第三个操作数相加:
1.10•21先前的结果。
1.00•24第三个操作数。
指数不匹配,请调整,然后添加:
0.00110•24之前的结果调整为匹配指数。
1.00•24第三个操作数。
――――――――――――
1.00110•24精确和,数字太多,必须四舍五入。
1.01•24四舍五入和。
对于第二个表达式,我们添加第二个和第三个操作数,然后添加第一个操作数:
Add second and third:
1.10 • 20 Second operand.
1.00 • 24 Third operand.
Exponents do not match, so adjust, then add:
0.000110 • 24 Second operand adjusted to match exponent.
1.00 • 24 Third operand.
――――――――――――――
1.000110 • 24 Exact sum, too many digits, must be rounded.
1.00 • 24 Rounded sum.
Add first operand and previous result:
1.10 • 20 First operand.
1.00 • 24 Previous result.
Exponents do not match, so adjust and then add:
0.000110 • 24 First operand adjusted to match exponent.
1.00 • 24 Previous result.
―――――――――――――
1.000110 • 24 Exact sum, too many digits, must be rounded.
1.00 • 24 Rounded sum.
添加第二个和第三个:
1.10•20秒操作数。
1.00•24第三个操作数。
指数不匹配,请调整,然后添加:
调整0.000110•24秒操作数以匹配指数。
1.00•24第三个操作数。
――――――――――――――
1.000110•24精确和,数字太多,必须四舍五入。
1.00•24四舍五入和。
将第一个操作数和上一个结果相加:
1.10•20第一个操作数。
1.00•24之前的结果。
指数不匹配,请调整,然后添加:
0.000110•24调整第一个操作数以匹配指数。
1.00•24之前的结果。
―――――――――――――
1.000110•24精确和,数字太多,必须四舍五入。
1.00•24四舍五入和。
第一个表达式产生1.01•24,而第二个表达式产生1.00•24。因此,操作数的加法顺序会影响结果。我的假设是加法的中间值可能有不同的舍入点错误。例如,a+b
可能导致舍入错误。而b+c
可能不会,或者结果值与最终值相加时可能会导致不同类型的浮点错误。添加括号可以使操作顺序和中间值更加清晰:
(a+b)+c
(c+b)+a
可能的重复实际上,总和可能高达48位,这取决于尾数(有效位)必须如何移位才能获得相同的指数。但事实上,结果往往必须四舍五入+1.