鱼C论坛

 找回密码
 立即注册
查看: 4685|回复: 16

double显示有误

[复制链接]
发表于 2012-9-25 09:09:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
int i=1,j=0;
double y=2,s=0,s=0;
a=y+j*pow(10,(-i));
s=a+pow(10,(-i));
调试中却显示这样   
s        2.1000000000000001
a        2.0000000000000000
为什么a 是17位有效数字,s最后的1从哪儿来的?

小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-25 09:22:38 | 显示全部楼层
别指望double的精度......
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-25 11:40:27 | 显示全部楼层
10进制的2.1不能用有限的2进制位表示,所以表示的一定是近似值。LZ试试2.5或2.75这些可以用2进制精确表示的数,就不会有误差
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-25 14:41:10 | 显示全部楼层

什么意思,如果要用2.1的时候呢
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-25 15:05:25 | 显示全部楼层
旅行 发表于 2012-9-25 14:41
什么意思,如果要用2.1的时候呢

比如:2.5可以表示为二进制数(1.1)
2.75可以表示为二进制数(1.11)
2.1不可能用有限位数的二进制数表示,又因为计算机内部只可能用有限位数表示一个数。所以该表示只可能是近似表示。就是说计算机里的2.1其实是一个非常接近2.1的数。

由于这个问题普遍存在,所以,C语言中我们认为float和double都是近似表示的(尽管有一些数确实可以精确表示如2.5)

当你确实需要非常精确地表示一个小数的时候,你只能通过其它办法用整数来表示。比如你要表示2.1元人民币,为了青雀表示,你只能表达为21角人民币或210分人民币

不过尽管float和double都是近似表示,但其实误差很小,在要求不是非常严格的情况下人们依旧使用它们,因为直接使用它们很简单
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-25 22:18:34 | 显示全部楼层
仰望天上的光 发表于 2012-9-25 15:05
比如:2.5可以表示为二进制数(1.1)
2.75可以表示为二进制数(1.11)
2.1不可能用有限位数的二进制数表示, ...

领教了
那,这里的17位有效数字怎么解释?
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-26 08:59:09 | 显示全部楼层
旅行 发表于 2012-9-25 22:18
领教了
那,这里的17位有效数字怎么解释?

计算机内部,double遵从IEEE754长浮点数标准,用64位存储.float遵从IEEE754短浮点数标准,用32位存储.

不过你这里使用的是printf函数.这个函数可以设置显示显示精度的.不过函数归函数,精度设置太高也没什么意义.因为硬件存储的最多才64位2进制数.LZ有兴趣,我就给个势力程序,任意设置下精度,但LZ一定要知道,这个精度设置超过了硬件实际表示的精度后,多出来的精度都是不可信的.
  1. #include <stdio.h>

  2. int main(){
  3.         double f = 2.1;
  4.         printf("%.17f\n",f);
  5.         printf("%.100f\n",f);
  6.         printf("%.200f\n",f);
  7. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-26 12:59:18 | 显示全部楼层
仰望天上的光 发表于 2012-9-26 08:59
计算机内部,double遵从IEEE754长浮点数标准,用64位存储.float遵从IEEE754短浮点数标准,用32位存储.

不 ...

领教了,谢啦
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-26 13:06:05 | 显示全部楼层
仰望天上的光 发表于 2012-9-26 08:59
计算机内部,double遵从IEEE754长浮点数标准,用64位存储.float遵从IEEE754短浮点数标准,用32位存储.

不 ...

等等,我是直接定义的   double a=0,s=0;  调试的时候发现s和a显示的是17位的
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-26 13:55:44 | 显示全部楼层
旅行 发表于 2012-9-26 13:06
等等,我是直接定义的   double a=0,s=0;  调试的时候发现s和a显示的是17位的

那是因为printf显示double的时候有个默认显示的精度
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-27 12:34:29 | 显示全部楼层
仰望天上的光 发表于 2012-9-26 13:55
那是因为printf显示double的时候有个默认显示的精度

没用printf,是单步调试,在下面的方框里显示的a 和 s的值是17位的
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-27 13:50:06 | 显示全部楼层
旅行 发表于 2012-9-27 12:34
没用printf,是单步调试,在下面的方框里显示的a 和 s的值是17位的

估计单步调试的时候IDE也是调用了类似printf的函数吧
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-27 13:55:49 | 显示全部楼层
仰望天上的光 发表于 2012-9-27 13:50
估计单步调试的时候IDE也是调用了类似printf的函数吧

那在过程中参加运算的a和s还是16位的,不会被第17位造成干扰吧?
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-27 14:11:26 | 显示全部楼层
在过程中参加运算的a和s都是64位2进制数.
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-27 21:14:00 | 显示全部楼层
仰望天上的光 发表于 2012-9-27 14:11
在过程中参加运算的a和s都是64位2进制数.

在过程中2.1000000000000001中的第二个1会不会参加运算?
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-9-27 21:37:56 | 显示全部楼层
旅行 发表于 2012-9-27 21:14
在过程中2.1000000000000001中的第二个1会不会参加运算?

2.1000000000000001只是表象,它反应的是一个64比特浮点数的真实存在。所以实际上没有什么.1那不过是IDE为了让你更方便地看到10进制数而转化出来的。这个数只能说是很接近原数的10进制表示,并不是原数。所以要参加运算也不是这个数参加运算。
小甲鱼最新课程 -> https://ilovefishc.com
 楼主| 发表于 2012-9-28 11:05:17 | 显示全部楼层
仰望天上的光 发表于 2012-9-27 21:37
2.1000000000000001只是表象,它反应的是一个64比特浮点数的真实存在。所以实际上没有什么.1那不过是IDE为 ...

   
谢啦
小甲鱼最新课程 -> https://ilovefishc.com
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-11-15 06:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表