C# - Int操作莫名其妙地返回负值

时间:2013-08-01 16:10:19

标签: c# floating-point int

操作如下:

public float InfectionPercent()
{
    return (infected + zombies) * 100 / population;
}

值为:

int infected = 20196093
int zombies = 1978138
int population = 32608521

返回的值为-63

100更改为100f可解决此问题。


为什么该操作返回-63而不是63

4 个答案:

答案 0 :(得分:8)

20196093 + 1978138 = 22174231
22174231 * 100 = 2 217 423 100

但是,Int.MaxValue为2 147 483 647,因此您破坏了最大值。

通过将100设置为float,您正在强制浮点乘法。有效的float值介于-3.4 × 10^38+3.4 × 10^38之间(这是340十亿分之一,即非常多),所以它确实是正确的。

答案 1 :(得分:3)

这是一个整数溢出错误

2,147,483,647是最大c#整数值

20,196,093 + 1,978,138 = 22,174,231

22,174,231 * 100 = 22,174,231 * 100 = 2,217,423,100

(整数溢出到-2,077,544,195

-2,077,544,195 / 32,608,521 = -63.71169655318007

转换为float可以防止出现这个问题,因为浮动不会长时间溢出,而且一旦浮动就会无限期地溢出。

答案 2 :(得分:1)

问题的解决方案是强制浮动乘法,就像使用100f一样(由Pierre-Luc Pineault解释的原因)。但是,如果您希望在未明确强制转换的情况下返回整数结果,请创建变量uint,因为它们只能是正数。

uint infected = 20196093
uint zombies = 1978138
uint population = 32608521

public uint InfectionPercent()
{
    return (infected + zombies) * 100 / population;
}

//output is 68 (float output is 68.00134)

可能不是瓶颈,但如果它是实时游戏,你可能会获得更好的表现,因为你避免将int投射到float(当然,这可能是微观的 - 优化取决于你调用它的频率。)

修改 - 正如Chris在评论中正确提到的那样,在这种情况下最好使用long代替uint

答案 3 :(得分:0)

一个整数可以容纳的最大数是2,147,483,647。如果你的变量被感染并且僵尸都是整数,那么它们会超过这个数字,因为{(被感染的+僵尸)* 100} = 2,217,423,100> 2,147,483,647。因为它最大化了整数,所以进入负数。尝试将感染和僵尸变量变为浮点数或通过将100变为100.00来强制浮点乘法。