乘以两个正Int32返回错误的否定答案?
我真的很难过这个。 我正在使用C#编写Windows Phone 7.5; 我从文本框中取出文本,将其解析为数组,然后使用Convert.ToInt32将每个数组元素转换为Int32,然后通过一系列数学计算运行生成的Int32值,将Int32值乘以并添加到硬编码数字(均取决于UI中选择的内容)。
一切都很好,直到我得到结果计算并将它们相乘:我从两个正数乘以得到一个负数! 这是我唯一一次使用源自使用Convert.ToInt32函数的方法的数字进行任何计算。 当它们被加,减,甚至分开时,数学运算正确。 但是当它们成倍增长时,没有骰子。 数学是完全错误的; 我仔细检查了LibreOffice Calc中的数学并且它不匹配。 当单步执行代码时,一切都是正确的,直到源自使用Convert.ToInt32函数的方法中的数字相乘。 有任何想法吗?
这些数字可能足以溢出Int32.MaxValue
。
考虑:
var r = Int32.MaxValue / 2; // r = 1073741823 var ans = r * 3; // ans = -1073741827
其原因是负整数在最大位中用1
表示,因此任何大于最大值的乘法在该位置将具有1
,这被解释为负值。
溢出是所有整数类型( int
, short
, byte
, sbyte
, char
, long
, ulong
, ushort
和uint
)的危险。 您可以使用浮点类型,例如float
或double
,但这会带来其他问题,例如舍入和平等问题。 您必须知道您期望的数字类型,然后您可以使用其他类型,如long
, uint
, ulong
或浮点类型,如double
或decimal
。 最后,如果您不知道会发生什么,您需要在输入上编写保护代码(例如将其包装在已checked { }
块[thanks,@ EricLippert]中 ) ,并在超出范围的值时处理它你为之设计的。
编辑:.Net 4.0+中的另一个选项是使用System.Numerics.BigInteger
,它可以避免任何溢出,但可能很慢。
快速而肮脏的解决方案就是将其中一个值转换为long
,然后将结果转换回int
,如果可能的话。
编辑:在这种情况下不需要使用BigInteger
,因为int x int
永远不会溢出long
。
它可能是一个Integer溢出exception。 即使您将数字存储在足够大的变量中,也可能发生这种情况。 示例(长,双等)
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