简体   繁体   English

将两个正整数Int32相乘会返回错误的负答案?

[英]Multiplying two positive Int32 returns incorrect, negative answer?

I'm really stumped on this one. 我真的很为难。 I'm coding in C# for Windows Phone 7.5; 我使用Windows Phone 7.5的C#进行编码; I am taking text from a text box, parsing it into an array, then converting each array element into an Int32 using Convert.ToInt32, then running the resulting Int32 values through a series of mathematical calculations, multiplying and adding the Int32 values to hardcoded numbers (all dependent upon what's selected in the UI). 我正在从文本框中获取文本,将其解析为数组,然后使用Convert.ToInt32将每个数组元素转换为Int32,然后通过一系列数学计算运行所得的Int32值,并将Int32值相乘并将其添加到硬编码数字中(全部取决于在UI中选择的内容)。

All is well until I take the resulting calculations and multiply them together: I'm getting a negative number from multiplying two positive numbers! 一切顺利,直到我将所得的计算结果乘以它们:我将两个正数相乘得到一个负数! This is the only time I am doing any calculations with both of the numbers that originated in the method that uses the Convert.ToInt32 function. 这是我唯一一次使用源自使用Convert.ToInt32函数的方法的两个数字进行任何计算的情况。 When they're added, subtracted, or even divided, the math comes out correctly. 将它们相加,相减甚至相除后,数学计算就正确了。 But when they're multiplied, no dice. 但是当它们相乘时,就没有骰子。 The math is totally wrong; 数学是完全错误的。 I double checked the math in LibreOffice Calc and it doesn't match. 我仔细检查了LibreOffice Calc中的数学,但不匹配。 When stepping through the code, everything's correct until the numbers that originated in the method that uses the Convert.ToInt32 function are multiplied together. 单步执行代码时,直到将使用Convert.ToInt32函数的方法中起源的数字相乘在一起,一切都是正确的。 Any ideas? 有任何想法吗?

The numbers are probably large enough to overflow Int32.MaxValue . 这些数字可能足够大, Int32.MaxValue溢出Int32.MaxValue

Consider: 考虑:

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

The reason for this is that negative integers are represented with a 1 in the largest bit, so any multiplication which is larger than the maximum value will have a 1 in this position, which is interpreted as a negative value. 原因是负整数在最大位用1表示,因此任何大于最大值的乘法在该位置都将有1 ,这被解释为负值。

Overflow is a danger with all integral types ( int , short , byte , sbyte , char , long , ulong , ushort , and uint ). 所有整数类型( intshortbytesbytecharlongulongushortuint )都有溢出的危险。 You could use a floating point type, like float or double , but this comes with other problems, like rounding and equality issues. 您可以使用浮点类型,例如floatdouble ,但这会带来其他问题,例如舍入和相等问题。 You have to know what kind of numbers you expect, then you might use other types like long , uint , ulong or a floating point type like double or decimal . 您必须知道期望使用哪种数字,然后才能使用其他类型,例如longuintulong或浮点类型(例如doubledecimal Ultimately, if you don't know what could happen, you need to write guard code on the input (eg wrap it in a checked { } block [thanks, @EricLippert] ) , and handle it when it is a value outside the range you've designed for. 最终,如果您不知道会发生什么,则需要在输入上编写保护代码(例如,将其包装在checked { }块中[感谢@EricLippert] ,并在该值超出范围时进行处理。您设计的。

EDIT: Another option in .Net 4.0+ is to use System.Numerics.BigInteger , which avoids any overflow, but can be slow. 编辑:.Net 4.0+中的另一个选项是使用System.Numerics.BigInteger ,它避免了任何溢出,但速度可能很慢。

The quick and dirty solution is just to cast one of the values to a long and then cast the result back to int , if possible. 快速而肮脏的解决方案是将值之一转换为long ,然后将结果转换回int (如果可能)。

Edit: There is no need to use BigInteger for this case as int x int can never overflow a long . 编辑:在这种情况下,无需使用BigInteger ,因为int x int永远不会long溢出。

Its probably a Integer overflow exception. 它可能是整数溢出异常。 It can occur even if you are storing the number in a variable that is big enough. 即使您将数字存储在足够大的变量中,也会发生这种情况。 Example(long,double etc) 示例(长,双等)

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

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

You can cast them before the sum and get the correct result 您可以将它们强制转换为总和,以获得正确的结果

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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM