热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么10/3它在C中是准确的?

如何解决《为什么10/3它在C中是准确的?》经验,为你挑选了1个好方法。

看看这段代码.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

再次,由最不重要的位.

至于实际结果如何四舍五入,我不能说.


推荐阅读
author-avatar
小辣椒jie
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有