【问题标题】:Multiplying two positive Int32 returns incorrect, negative answer?将两个正 Int32 相乘返回不正确的否定答案?
【发布时间】:2013-03-09 20:12:19
【问题描述】:

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

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

【问题讨论】:

  • 您想向我们展示您的代码吗?
  • 听起来像是溢出。你在使用大数字吗?
  • 首先,如果您需要超出 int 范围的准确结果,请使用 long、decimal 或 BigIntegers 进行算术运算。其次,如果你认为溢出是一个bug并且你想找到它,那么将你的算术放在checked { ... } 块中,任何整数溢出都会成为异常。这将帮助您找到错误。

标签: c# int32


【解决方案1】:

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

考虑:

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

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

对于所有整数类型(intshortbytesbytecharlongulongushortuint),溢出都是一种危险。您可以使用浮点类型,例如floatdouble,但这会带来其他问题,例如舍入和相等问题。你必须知道你期望什么样的数字,然后你可能会使用其他类型,如 longuintulong 或浮点类型,如 doubledecimal。最终,如果您不知道会发生什么,您需要在输入 上编写保护代码(例如,将其包装在 checked { } 块中 [thanks, @EricLippert]) em>,并在它的值超出您设计的范围时处理它。

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

【讨论】:

  • 感谢您的解释。当我乘法时,我可能只使用 System.Numerics.BigInteger。该应用程序应该可以承受很小的速度冲击;而且我不应该经常收到大量数据。
【解决方案2】:

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

编辑:在这种情况下不需要使用BigInteger,因为int x int 永远不会溢出long

【讨论】:

  • 有时这是快速而干净的解决方案! :)
  • 如果他已经溢出,已经知道不可能有int结果。
  • @codekaizen:但是从未经检查的操作中确定这一点可能会更昂贵。在检查的上下文中,您将节省异常的成本,从我的测试来看,它更快。
  • int.MinValue 是-2^31,它的平方是2^62,正好在long的范围内。
【解决方案3】:

它可能是整数溢出异常。即使您将数字存储在足够大的变量中,它也可能发生。示例(长、双等)

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 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多