乘以两个正Int32返回错误的否定答案?

时间:2013-03-09 20:12:19

标签: c# int32

我真的很难过这个。我正在使用C#编写Windows Phone 7.5;我从文本框中取出文本,将其解析为数组,然后使用Convert.ToInt32将每个数组元素转换为Int32,然后通过一系列数学计算运行生成的Int32值,将Int32值乘以并添加到硬编码数字(全部取决于在UI中选择的内容)。

一切都很好,直到我得出结果计算并将它们相乘:我从两个正数乘以得到一个负数!这是我唯一一次使用源自使用Convert.ToInt32函数的方法的数字进行任何计算。当它们被加,减,甚至分开时,数学运算正确。但是当它们成倍增加时,没有骰子。数学是完全错误的;我仔细检查了LibreOffice Calc中的数学并且它不匹配。在单步执行代码时,一切都是正确的,直到源自使用Convert.ToInt32函数的方法中的数字相乘。有什么想法吗?

3 个答案:

答案 0 :(得分:12)

这些数字可能足以溢出Int32.MaxValue

考虑:

var r = Int32.MaxValue / 2;     // r = 1073741823
var ans = r * 3;                // ans = -1073741827

这样做的原因是负整数在最大位中用1表示,因此任何大于最大值的乘法在此位置都会有1,这被解释作为负值。

溢出是所有整数类型的危险(intshortbytesbytecharlong,{{ 1}},ulongushort)。您可以使用浮点类型,例如uintfloat,但这会带来其他问题,例如舍入和平等问题。您必须知道您期望的数字类型,然后您可以使用其他类型,例如doublelonguint或浮点类型,例如ulong或{{1 }}。最后,如果您不知道会发生什么,您需要在输入上编写保护代码(例如将其包装在double [thanks,@ EricLippert] 中) ,并在超出您设计范围的值时处理它。

编辑:.Net 4.0+中的另一个选项是使用decimal,这可以避免任何溢出,但可能会很慢。

答案 1 :(得分:3)

快速而肮脏的解决方案就是将其中一个值转换为long,然后将结果转换回int,如果可能的话。

修改:在这种情况下无需使用BigInteger,因为int x int永远不会溢出long

答案 2 :(得分:0)

它可能是一个Integer溢出异常。即使您将数字存储在足够大的变量中,也会发生这种情况。示例(长,双等)

int one = int.MaxValue;
int two = int.MaxValue;

long sum = (long)(one + two); //Returns -2, because the cast was after the sum
                             //(long) -2.

您可以在总和之前投射它们并获得正确的结果

int one = int.MaxValue;
int two = int.MaxValue;

long sum = (long) one + (long)two; //Returns 4294967294, it casts both the 
                                   //integer to long and then adds them