我真的很难过这个。我正在使用C#编写Windows Phone 7.5;我从文本框中取出文本,将其解析为数组,然后使用Convert.ToInt32将每个数组元素转换为Int32,然后通过一系列数学计算运行生成的Int32值,将Int32值乘以并添加到硬编码数字(全部取决于在UI中选择的内容)。
一切都很好,直到我得出结果计算并将它们相乘:我从两个正数乘以得到一个负数!这是我唯一一次使用源自使用Convert.ToInt32函数的方法的数字进行任何计算。当它们被加,减,甚至分开时,数学运算正确。但是当它们成倍增加时,没有骰子。数学是完全错误的;我仔细检查了LibreOffice Calc中的数学并且它不匹配。在单步执行代码时,一切都是正确的,直到源自使用Convert.ToInt32函数的方法中的数字相乘。有什么想法吗?
答案 0 :(得分:12)
这些数字可能足以溢出Int32.MaxValue
。
考虑:
var r = Int32.MaxValue / 2; // r = 1073741823
var ans = r * 3; // ans = -1073741827
这样做的原因是负整数在最大位中用1
表示,因此任何大于最大值的乘法在此位置都会有1
,这被解释作为负值。
溢出是所有整数类型的危险(int
,short
,byte
,sbyte
,char
,long
,{{ 1}},ulong
和ushort
)。您可以使用浮点类型,例如uint
或float
,但这会带来其他问题,例如舍入和平等问题。您必须知道您期望的数字类型,然后您可以使用其他类型,例如double
,long
,uint
或浮点类型,例如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