c语言double的精度问题?

saint13 2012-07-05 01:46:38
hi 各位,
double a=1000000.0;
double b=0.2;
double c=10000;
double d;
d=(int)(a/(b*c)); //语句1:这里返回的是499.

如果是
d=a/(b*c); //语句2:这里返回的是500.00
d=(int)d; //

各位,很奇怪,为何语句1和语句2会产生不同的结果?
另外,如果是语句1的形式,我在gdb下调试时,直接print (int)(a/(b*c)),结果是500,也不是499
谢!
...全文
1346 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
ForestDB 2013-03-31
  • 打赏
  • 举报
回复

      movq    %rax, -24(%rbp)           |      movq    %rax, -24(%rbp)
      movsd   -16(%rbp), %xmm0          |      movsd   -16(%rbp), %xmm0
      movapd  %xmm0, %xmm1              |      movapd  %xmm0, %xmm1
      mulsd   -24(%rbp), %xmm1          |      mulsd   -24(%rbp), %xmm1
      movsd   -8(%rbp), %xmm0           |      movsd   -8(%rbp), %xmm0
      divsd   %xmm1, %xmm0              |      divsd   %xmm1, %xmm0
  --------------------------------------|      cvttsd2si   %xmm0, %eax          
  --------------------------------------|      cvtsi2sd    %eax, %xmm0          
      movsd   %xmm0, -32(%rbp)          |      movsd   %xmm0, -32(%rbp)
      movl    $0, %eax                  |      movl    $0, %eax
      leave                             |      leave
      ret                               |      ret
可以在执行时看看xmm0的值是多少,应该不是完全等于500.0 而精度就在cvttsd2si和cvtsi2sd的转来转去中丢失掉了。
ForestDB 2013-03-31
  • 打赏
  • 举报
回复
不考虑赋值 单(a/(b*c))应该是几?
zhuqi12580 2013-03-31
  • 打赏
  • 举报
回复
引用 12 楼 nice_cxf 的回复:
说是精度问题的,你们在gcc下仔细测试过没? 如果定义一个double e=b*c; 那么d=(int)(a/e)就是500,而(int)(a/(b*c))就是499,这跟精度有什么关系?
只能说一句,你太相信gcc的精度处理了 为什么前者是500,后者是499就是精度问题, 后者可能就是(int)(a/(2000.000000000000001))结果就是499 前者当然是500了
nice_cxf 2012-07-06
  • 打赏
  • 举报
回复
说是精度问题的,你们在gcc下仔细测试过没?
如果定义一个double e=b*c;
那么d=(int)(a/e)就是500,而(int)(a/(b*c))就是499,这跟精度有什么关系?
cloudszhang 2012-07-06
  • 打赏
  • 举报
回复
我在VC2008下,语句1也是500,而不是499
double a=1000000.0;
double b=0.2;
double c=10000;
double d;
int e=(int)(a/(b*c)); //语句1:这里返回的是499.
cout << e << endl;

d=a/(b*c); //语句2:这里返回的是500.00
cout << d << endl;
d=(int)d; //
cout << d << endl;

return 0;
AnYidan 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

vs2008下是500,500,但是gcc下的确是499,500按说没区别的啊,难道是gcc的bug?
[/Quote]

window 一向擅长 践踏别人的标准, 不过此处它可能有更精确的处理,比如利用或模拟了浮点数扩展的精度。
saint13 2012-07-06
  • 打赏
  • 举报
回复
楼上说到一个点上了。
wizard_tiger 2012-07-05
  • 打赏
  • 举报
回复
楼上都说了,这个是精度问题。
northcan 2012-07-05
  • 打赏
  • 举报
回复
d=(int)(a/(b*c)); //语句1:这里返回的是499.

a/(b*c)的计算结果可能是499.xxxx
(int)强制类型转换,只保留了整数部分。

3楼说的好
赵4老师 2012-07-05
  • 打赏
  • 举报
回复
二进制小数0.1,表示1/2即0.5
三进制小数0.1,表示1/3即0.33333...
四进制小数0.1,表示1/4即0.25
……
十进制小数0.1,表示1/10即0.1
pathuang68 2012-07-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

用10进制小数不能精确表示某些三进制小数0.1(3)=0.33333333333……(10)
同理,用二进制小数也不能精确表示某些10进制小数。

参考float.h
C/C++ code
...
#define DBL_DIG 15 /* # of decimal digits of precision */
#define ……
[/Quote]

“三进制小数0.1(3)=0.33333333333……(10)”三进制中,怎么会出来3呢?赵大侠发明滴?
WinPhone9 2012-07-05
  • 打赏
  • 举报
回复
同意赵老师观点,计算机精度问题
nice_cxf 2012-07-05
  • 打赏
  • 举报
回复
vs2008下是500,500,但是gcc下的确是499,500按说没区别的啊,难道是gcc的bug?

pathuang68 2012-07-05
  • 打赏
  • 举报
回复
1. 不同的编译器的处理会所有不同,比如,楼主的“语句1:这里返回的是499”处,在VS2010上就是500
2. double的1.0,实际上在计算机中有可能是0.9999999999999...,此时如果你将它转型为int,它就是0了

这是数字计算机固有缺陷,无法回避。
W170532934 2012-07-05
  • 打赏
  • 举报
回复
赵老师说的是。精度问题
赵4老师 2012-07-05
  • 打赏
  • 举报
回复
用10进制小数不能精确表示某些三进制小数0.1(3)=0.33333333333……(10)
同理,用二进制小数也不能精确表示某些10进制小数。

参考float.h
...
#define DBL_DIG 15 /* # of decimal digits of precision */
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */
#define DBL_MANT_DIG 53 /* # of bits in mantissa */
#define DBL_MAX 1.7976931348623158e+308 /* max value */
#define DBL_MAX_10_EXP 308 /* max decimal exponent */
#define DBL_MAX_EXP 1024 /* max binary exponent */
#define DBL_MIN 2.2250738585072014e-308 /* min positive value */
#define DBL_MIN_10_EXP (-307) /* min decimal exponent */
#define DBL_MIN_EXP (-1021) /* min binary exponent */
#define _DBL_RADIX 2 /* exponent radix */
#define _DBL_ROUNDS 1 /* addition rounding: near */
...

70,021

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧