浮点求和精度问题

wyl0502 2006-09-27 08:00:32
+ 928455029464035210000000000.0f
38942226439011207000000000000000000.0f
-----------------------------------
38942227367466237000000000000000000.0f
float的尾数位才23位,为什么能有这么高的精度?
我用自己写的软浮点计算出来的结果为38942226439011207000000000000000000.0f
...全文
405 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
晨星 2006-09-27
  • 打赏
  • 举报
回复
你可以反汇编看一下,当
float f = 0.1;
printf("%f", f);
时,压栈的参数是4个字节还是8个字节。
晨星 2006-09-27
  • 打赏
  • 举报
回复
试出过一两个精确的也不是没可能。
但float只能“保证”6到7位的精度,超过了并不是说“肯定”不对,只是不能保证,只是比较危险,比较难说,而且很容易就能找到不正确的例子,如此而已。

关于printf打印float,我没说市面上任何一种库都是那么做的,这个没研究过,但所有那些不分"%lf"与"%f"的都是这么做的。
而scanf通常则严格区分"%f"和"%lf"。
晨星 2006-09-27
  • 打赏
  • 举报
回复
许多库都的printf都是那样实现浮点数打印的,所以打印double完全不用“%lf”,“%f”即可。
每一位都精确吗?为什么在俺的机器上只有7位精确。:(
wyl0502 2006-09-27
  • 打赏
  • 举报
回复
"这个在printf的处理过程中,作为参数传入的,以及printf打印的,都是double。"凭什么这么说?
"不过既使它传入、打出的是double"谁说的???
"事实上就是不准确了"那就错了,我刚才试了一个结果是精确的,不过那句好像是转成double再进行运算的了,现在问题不在这.
晨星 2006-09-27
  • 打赏
  • 举报
回复
“float的精度是7位有效数字”跟“printf能打印7位float”这两句话没有任何关系。
正确的说法应该是:“printf打印一个float的时候,不管打出了多少位,通常只有6到7位有效数字是准确的”。
晨星 2006-09-27
  • 打赏
  • 举报
回复
首先
printf("a=%f\r\n",a);
这个在printf的处理过程中,作为参数传入的,以及printf打印的,都是double。不过那是printf的底层实现问题,跟咱们讨论的问题关系不大,怪我把话题叉开了,不好意思,呵呵。

不过既使它传入、打出的是double,这个double也是原来那个float转换过去的,不具备直接double计算的精度。

至于它打印出那么多,说明不了任何问题,它只是觉得他可以打印那么多,每一位是否准确它也不知道,事实上就是不准确了,很明显。
mu_yang 2006-09-27
  • 打赏
  • 举报
回复

*(float*)(&l);

这是不知所云的语句

wyl0502 2006-09-27
  • 打赏
  • 举报
回复
steedhorse(晨星) :
谢谢你的回复,
printf("%f",928455029464035210000000000.f+38942226439011207000000000000000000.f);
这句并没错,上面那句只是程序里摘出来的一行,可是我搞不懂后面贴出来的的那一段代码.
float rand_float()只能产生float而不能产生double,可是printf出来的远不止7位.
a=rand_float();
printf("a=%f\r\n",a);
这两句不可能产生double出来吧?
晨星 2006-09-27
  • 打赏
  • 举报
回复
哦,不对,我说的可能跟这个不是一回事。
printf对于浮点数统统是转化成double压栈和找印的。

但问题是,对于“精度”的观察不是看printf能打出多少位,printf能打的位数多着呢,关键是有多少位是准确的。
float能保证6到7位有效数字的精度,而double可以保证15到18位。

我刚刚在VC下运行了一下程序,结果跟你原来帖的并不一样,而是
38942226439011207000000000000000000.f
(跟第二个数完全一样),换句话说,从第8个有效数字开始,已经完全不准确了,打出来也只是“占地方好看”而已。
晨星 2006-09-27
  • 打赏
  • 举报
回复
printf("%f",928455029464035210000000000.f+38942226439011207000000000000000000.f);
——这个是double

楼主你这样试试:
float f1 = 928455029464035210000000000.f;
float f2 = 38942226439011207000000000000000000.f
float f3 = f1 + f2;
printf("%f", f3);
wyl0502 2006-09-27
  • 打赏
  • 举报
回复
以上的代码结果正确,产生"高精度"的代码如下:
另人不解的是,32位的float为什么能printf出那么多位.

#include <stdio.h>
#include <stdlib.h>

float rand_float(){
int i0=rand();
int i1=rand();
unsigned long l=(unsigned long)(i0<<16)+i1;
return *(float*)(&l);
}
int main(){
float a;
for(int i=0;i<10;i++){
a=rand_float();
printf("a=%f\r\n",a);
}
}
结果:
a=0.000000
a=0.000000
a=7380662.000000
a=0.000000
a=15895356454130710000000000.000000
a=0.000000
a=33953870400978944.000000
a=0.000000
a=0.000000
a=0.000000
wyl0502 2006-09-27
  • 打赏
  • 举报
回复
"软浮点计算"?
我用unsigned long来表示float,浮点的加法自己实现
wyl0502 2006-09-27
  • 打赏
  • 举报
回复
printf("%f",928455029464035210000000000.f+38942226439011207000000000000000000.f);
这样不是double的吧?
飞哥 2006-09-27
  • 打赏
  • 举报
回复
你的是 多少位的计算机啊?
偶的肯定不行
mu_yang 2006-09-27
  • 打赏
  • 举报
回复
我恐怕楼主不知道什么叫"精度"
晨星 2006-09-27
  • 打赏
  • 举报
回复
不过还是不太相信,能把你的程序帖一下吗?
lj860603 2006-09-27
  • 打赏
  • 举报
回复
对呵,偶也有点纳闷,能这样精确到这么多位??
lj860603 2006-09-27
  • 打赏
  • 举报
回复
不懂。帮顶。
飞哥 2006-09-27
  • 打赏
  • 举报
回复
能表示那么长的吗?
晨星 2006-09-27
  • 打赏
  • 举报
回复
哦,没看清,不好意思。
加载更多回复(3)

69,382

社区成员

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

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