铸造时不同的截断结果

时间:2010-12-20 20:06:27

标签: c casting rounding truncate

我在预测我的C代码将如何截断结果时遇到一些困难。请参阅以下内容:

float fa,fb,fc;
short ia,ib;

fa=160
fb=0.9;
fc=fa*fb;
ia=(short)fc;
ib=(short)(fa*fb);

结果是ia = 144,ib = 143。

我可以理解这两种结果的推理,但我不明白为什么这两种计算的处理方式不同。任何人都可以向我推荐这种行为的定义或解释差异吗?

编辑:结果使用英特尔酷睿i3-330m上的MS Visual C ++ Express 2010进行编译。我在同一台机器上的Virtual Box下的gcc版本4.4.3(Ubuntu 4.4.3-4ubuntu5)上得到了相同的结果。

3 个答案:

答案 0 :(得分:7)

允许编译器对fa*fb之类的子表达使用比分配给float变量fc时使用的精度更高的精度。所以它是fc=部分,它稍微改变了结果(然后发生了整数截断的差异)。

答案 1 :(得分:3)

aschepler解释了正常情况的机制,但代码的基本问题是在代码中使用不存在的值作为float,这取决于代码的值它以不稳定的方式逼近。如果你想乘以0.9(实际数字0.9 = 9/10,而不是浮点值0.90.9f),你应该乘以9然后除以10,或者忘记浮点类型并使用十进制算术库。

一个廉价而肮脏的方法围绕这个问题,当不稳定点被隔离时,如你的例子所示,只是添加一个值(通常为0.5),你知道它将大于误差但小于与截断前的下一个整数。

答案 2 :(得分:0)

这取决于编译器。在我的(gcc 4.4.3)中,它为两个表达式产生相同的结果,即-144,可能是因为相同的表达式被优化掉了。

其他人很好地解释了发生了什么。换句话说,我会说差异可能是因为你的编译器在执行乘法之前在内部将浮点数提升到80位fpu寄存器,然后转换回float或short。

如果你写ib = (short)(float)(fa * fb);我的假设是正确的,你应该得到与将fc简化为短的结果相同的结果。