我在代码中有以下声明:
int a = (int)( (float)(b * 1000) / (float)c + .5f );
其中b
也是int
,
c
是一个unsigned int
,其值为常数(在我的测试运行中为15)
此语句位于while循环中,其中b
在每次迭代时递增1。
此代码工作正常,直到我决定在Visual Studio中打开优化标记(最大化速度)。之后,a
会随机进入溢出(即它的值为-2147483647
)。在进一步调查时,这种溢出曾经发生在不同的b
值。在我观察到的测试运行中,溢出发生的b值在9-12之间。
解决问题的方法是进行如下图所示的小改动:
int a = (int)( (b * 1000.f) / c + .5f );
有关这是如何帮助的任何想法?它工作正常,但我不明白为什么?
编辑:根据评论添加更多信息:
在记录时,我观察到:
(float)(b * 1000) / (float)c + .5f
被评估为一个非常大的值,当类型转换为int
导致溢出时。然而,单独地,float(b*1000)
和float(c)
被正确计算。
答案 0 :(得分:1)
b * 1000
很有可能溢出int
类型;执行此操作的行为是 undefined 。
删除所有那些混淆的强制转型,并使用
b * 1000.0 / c + 0.5
代替。 1000.0
是double
字面值,会导致第一个字词以浮点计算。
在转换回int
之前,您应该检查表达式的大小,特别是如果c
很小的话。 std::numeric_limits
对此很有用。
答案 1 :(得分:0)
b * 1000
为int * int
,因此会发生整数乘法,并且存在更高的溢出风险。 (有符号整数aritimetic中的溢出是未定义的行为)
将b
投射到float
也可以解决此问题。
int a = (int)( (float)b * 1000 / (float)c + .5f );