作者:小辣椒jie | 来源:互联网 | 2023-01-06 18:02
看看这段代码.10/3返回3.333333 2538 604736328125000当我在calcutor中乘以3得到9.99,但如果通过代码做同样的话我得到10.00.怎么可能?
#include
#include
int main() {
float v = 10.f/3.f;
float test = v*3.f;
printf("10/3 => %25.25f \n (10/3)*3 => %25.25f\n",v,test);
return 0;
}
这是没有printf的汇编代码,使用默认的gcc 7.2.1参数编译:
0000000000400497 :
400497: 55 push rbp
400498: 48 89 e5 mov rbp,rsp
40049b: f3 0f 10 05 b1 00 00 movss xmm0,DWORD PTR [rip+0xb1] # 400554 <_IO_stdin_used+0x4>
4004a2: 00
4004a3: f3 0f 11 45 fc movss DWORD PTR [rbp-0x4],xmm0
4004a8: f3 0f 10 4d fc movss xmm1,DWORD PTR [rbp-0x4]
4004ad: f3 0f 10 05 a3 00 00 movss xmm0,DWORD PTR [rip+0xa3] # 400558 <_IO_stdin_used+0x8>
4004b4: 00
4004b5: f3 0f 59 c1 mulss xmm0,xmm1
4004b9: f3 0f 11 45 f8 movss DWORD PTR [rbp-0x8],xmm0
4004be: b8 00 00 00 00 mov eax,0x0
4004c3: 5d pop rbp
4004c4: c3 ret
4004c5: 66 2e 0f 1f 84 00 00 nop WORD PTR cs:[rax+rax*1+0x0]
4004cc: 00 00 00
4004cf: 90 nop
我认为mulss是由CPU功能四舍五入的.
需要注意的是,GNU BC程序中的10/3返回3.3333333333333333333333(*3 => 9.9999),SciLab中返回3.333333333333333 4813 631(*3 => 10).
1> dbush..:
你最终得到的结果恰好是10,因为表示恰好是这样的.我对float和double的实现都是一样的.
让我们看一个使用double的例子:
如果我们10./3.
使用十六进制浮点表示法打印出来%a
,我们得到:
0x1.aaaaaaaaaaaabp+1
这与IEEE754双重表示相匹配0x401aaaaaaaaaaaab
.
以上数字归一化为:
0x3.5555555555558
二进制:
11.0101010101010101010101010101010101010101010101011
为了简单起见,让我们添加三次而不是乘以3:
11.0101010101010101010101010101010101010101010101011
+ 11.0101010101010101010101010101010101010101010101011
---------------------------------------------------------
110.1010101010101010101010101010101010101010101010111
+ 11.0101010101010101010101010101010101010101010101011
---------------------------------------------------------
1010.0000000000000000000000000000000000000000000000000
这正好是10.
编辑:
看起来我设法在最后几位数字处理数学.实际总和:
11.0101010101010101010101010101010101010101010101011
+ 11.0101010101010101010101010101010101010101010101011
---------------------------------------------------------
110.1010101010101010101010101010101010101010101010110
+ 11.0101010101010101010101010101010101010101010101011
---------------------------------------------------------
1010.0000000000000000000000000000000000000000000000001
所以它不完全是 10,而是最不重要的一点.
我注意到使用float时有类似的区别.
10.f/3.f
印有%a
:
0x1.aaaaaap+1
标准化:
0x3.555554
二进制:
11.0101010101010101010101
然后我们添加:
11.0101010101010101010101
+ 11.0101010101010101010101
------------------------------
110.1010101010101010101010
+ 11.0101010101010101010101
------------------------------
1001.1111111111111111111111
再次,由最不重要的位.
至于实际结果如何四舍五入,我不能说.