有点古怪,无法理解,请高手解疑!!

GZ 2004-04-23 02:06:23
#include<stdio.h>

void main()
{
float revise = 0.3;
short value = 10;
short result_1 = (short)(revise*value);
short result_2 = (short)(revise*0.3);
printf("the result_1 is %d!\n",result_1);
printf("the result_2 is %d!\n",result_2);
}
怎么result_1 == 3,而 result_2 == 1啊!???
...全文
73 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
GZ 2004-04-28
  • 打赏
  • 举报
回复
困惑了这么多天终于,解决了谢谢楼上的了!!!!
pgyssg 2004-04-28
  • 打赏
  • 举报
回复
结果都是3
nobush 2004-04-28
  • 打赏
  • 举报
回复
终于可以说服自己了:
都是二进制惹的祸!
原因在于0.3不能精确地用二进制表示!
所以才会这样.
用从tc2.0到BCC55R的编译器结果都是这么离奇,至于VC正常可能是微软的编译器在这方面作了优化,所以才符合常人的逻辑.而BORLAND的编译器也是完全符合机器的逻辑!
手工换算0.3的二进制表示:
0.010011001……除不尽!
从我手中资料——古老的286计算机组成原理上写明:
286对浮点实数的处理用32位,双精度浮点实数用64位;
临时实数用80位,且不使用隐藏位——这个好理解:临时数在计算过程中要多保留几位提高精度……
由于0.3的二进制无限长,必然要有误差处理。
286对此是采用舍入处理:(奔腾也类似)
超过表示范围的数被丢掉,
当丢失的最高位为1,以下各位不全为0时,则执行在尾数最低位入1的修正操作;否则不操作。
可见:舍入与否的概率各占一半!
本程序 float revise = 0.3;时,是写入一个内存地址,32位二进制数,估计它符合舍入条件,尾数最低位入1。因此,实际上 该地址空间应略大于0.3把它乘以100000以上的数应该可以证明。
short result_1 = (short)(revise*value);结果把3点零几取整得3 。
而:short result_2 = (short)(0.3*value);0.3是作为立即数参加运算,在临时数空间里是80位二进制表示的,它却不符合舍入条件。即运算数应是比0.3略小一点为0.299999……所以最后结果为2。
是否舍入不是一眼就可看清的,除非你用手算到小数点后24、64位以上……(这么说人还是比计算机精确哟 :)
为证明此假设有根据,而原程序误差并非是因为直接数就不精确赋值变量就一定精确:下面一段代码
float revise = 0.9;
short value = 10;
short result_1 = (short)(revise*value);
short result_2 = (short)(0.9*value);
printf("the result_1 is %d!\n",result_1);
printf("the result_2 is %d!\n",result_2);
运行结果:
the result_1 is 8!
the result_2 is 9!
看反过来了吧
这个题也再次教育我们对于浮点数,不要轻易==判断其是否等于定值的道理!


各位看还有什么不对没有
GZ 2004-04-28
  • 打赏
  • 举报
回复
哈哈,晚上等着你消息了!
nobush 2004-04-28
  • 打赏
  • 举报
回复
明白了! 晚上来写解释
GZ 2004-04-26
  • 打赏
  • 举报
回复
最后一次up,faint!~
GZ 2004-04-26
  • 打赏
  • 举报
回复
up一下,看今天能不能有结果!?
wxh163000 2004-04-26
  • 打赏
  • 举报
回复
ithe result_1 is 3!
the result_2 is 0!

eliner 2004-04-25
  • 打赏
  • 举报
回复
应该依赖于不同的编译器把
我用VC都是3
Jinvzhang 2004-04-25
  • 打赏
  • 举报
回复
我的VC6.0编译出来结果是
the result_1 is 3!
the result_2 is 3!
呵呵。。。。。
GZ 2004-04-25
  • 打赏
  • 举报
回复
是楼上的意思,我怎么又把2写成了1
郁闷!!!
ync111 2004-04-25
  • 打赏
  • 举报
回复
本人在作浙江大学上的题 以作了几十题
但没到题都要发送好多编才能对
有那位大哥大姐愿意和我一起做的; 以求共同发展;
请记下我的QQ:284301276或272656303
我的邮箱:ync999@163.com
GZ 2004-04-25
  • 打赏
  • 举报
回复
如果把revise变成双精度的,连result_1也是2了
GZ 2004-04-25
  • 打赏
  • 举报
回复
谢谢楼上的忠告,但是必须用类型转换,但是程序改了一下
#include<stdio.h>

void main()
{
float revise = 0.3;
short value = 10;
short result_1 = (short)(revise*value);

// short result_2 = (short)(0.3*value);
float result_2 = 0.3*value;

printf("the result_1 is %d!\n",result_1);
// printf("the result_2 is %d!\n",result_2);
printf("the result_2 is %d!\n",(short)result_2);
}
就 result_2 == 3 了

alula 2004-04-25
  • 打赏
  • 举报
回复
不要惊讶。
没有任何一本C/C++的书告诉你浮点 强制转换为整形的运算规则。

教训:不要野蛮的、想当然的使用强制类型转换。
bshaozi 2004-04-25
  • 打赏
  • 举报
回复
没必要吧
dongfangxuhua 2004-04-25
  • 打赏
  • 举报
回复
这可能是编译器的原因吧
GZ 2004-04-25
  • 打赏
  • 举报
回复
我用TC和g++都是一样的结果,可能是编译器不同就有不同结果!
nobush 2004-04-23
  • 打赏
  • 举报
回复
天啊!
我:TC 、BCC都是:

result_2 == 2 ???
GZ 2004-04-23
  • 打赏
  • 举报
回复
真的不好意思!再次向大家表示抱歉啊
加载更多回复(13)

70,035

社区成员

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

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