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

#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啊!???
[341 byte] By [laughable-Iv] at [2008-4-13]
# 1
错了,result_2 == 2
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 2
vc.net 2002

the result_1 is 3!
the result_2 is 0!
goodname-叶落知秋 at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 3
我用的是 gcc和tc3.0

laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 4
结果是
result_1 == 3,而 result_2 == 0

revise*value=0.3*10=3.0
然后(short)3.0==3 是截断取整
所以result_1 == 3

revise*0.3=0.3*0.3==0.09
(short)0.09==0
所以result_2 == 0
cngdzhang at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 5
cngdzhang()完全正确
doomleo-leo at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 6
我想大部分的结果应该如cngdzhang()
我觉得如果真的如楼主所说的,
应该是编译器的关系,
它取整的时候应该类似于ceil(),
有小数就会按进1取,结果就是1,
故与编译器有关系,楼主问题得解!
mrubbish-Ghost@rubbish at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 7
应该跟编译器没关系。浮点转整数就是去掉小数部分的。
# 8
与四楼意见保持一致!
可能是楼主的编译器所致吧.
另外,楼主既然已经定义result_1为short型,其实已经不必显式强制类型转换了.系统会自动隐式转换的,,
# 9
tc下:(short)(revise*0.3);result_2结果为:0
如果改成(short)(revise*3.3);result_2结果还是为:0
但改成(short)(revise*3.4);result_2结果还是为:1
你多试几个数字就知道怎么回事了

prdiga-巴蒂 at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 10
第三句‘但改成(short)(revise*3.4);result_2结果还是为:1‘改成‘但改成(short)(revise*3.4);result_2结果变成:1'
prdiga-巴蒂 at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 11
应该是0
yonyon-江南菜子 at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 12
不好意思是我写错了,向各位大哥认错了!!
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 13
是这样的
#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);
printf("the result_1 is %d!\n",result_1);
printf("the result_2 is %d!\n",result_2);
}
怎么result_1 == 3,而 result_2 == 1啊!???

真的不好意思!!!
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 14
真的不好意思!再次向大家表示抱歉啊
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 15
天啊!
我:TC 、BCC都是:

result_2 == 2 ???
nobush at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 16
是楼上的意思,我怎么又把2写成了1
郁闷!!
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 17
我的VC6.0编译出来结果是
the result_1 is 3!
the result_2 is 3!
呵呵。。。。。
Jinvzhang-小虫BBQ at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 18
应该依赖于不同的编译器把
我用VC都是3
eliner-eliner at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 19
我用TC和g++都是一样的结果,可能是编译器不同就有不同结果!
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 20
这可能是编译器的原因吧
dongfangxuhua-xuhua at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 21
没必要吧
# 22
不要惊讶。
没有任何一本C/C++的书告诉你浮点 强制转换为整形的运算规则。

教训:不要野蛮的、想当然的使用强制类型转换。
alula-alula at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 23
谢谢楼上的忠告,但是必须用类型转换,但是程序改了一下
#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 了

laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 24
如果把revise变成双精度的,连result_1也是2了
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 25
本人在作浙江大学上的题 以作了几十题
但没到题都要发送好多编才能对
有那位大哥大姐愿意和我一起做的; 以求共同发展;
请记下我的QQ:284301276或272656303
我的邮箱:ync999@163.com
ync111-紫梦 at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 26
up一下,看今天能不能有结果!?
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 27
最后一次up,faint!~
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 28
ithe result_1 is 3!
the result_2 is 0!

wxh163000-简单! at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 29
明白了! 晚上来写解释
nobush at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 30
哈哈,晚上等着你消息了!
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 31
终于可以说服自己了:
都是二进制惹的祸!
原因在于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!
看反过来了吧
这个题也再次教育我们对于浮点数,不要轻易==判断其是否等于定值的道理!

各位看还有什么不对没有
nobush at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 32
结果都是3
pgyssg-breeze at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...
# 33
困惑了这么多天终于,解决了谢谢楼上的了!!
laughable-Iv at 2007-10-25 > top of Msdn China Tech,C/C++,C语言...