【问题标题】:Why does Int32.MaxValue * Int32.MaxValue == 1?为什么 Int32.MaxValue * Int32.MaxValue == 1?
【发布时间】:2011-03-01 08:55:22
【问题描述】:

我知道,Int32.MaxValue * Int32.MaxValue 会产生一个大于Int32 的数字;但是,这句话不应该引​​发某种异常吗?

我在执行IF (X * Y > Z) 之类的操作时遇到了这个问题,所有这些都是Int32XY 足够大,你从 X * Y 得到一个虚假值。

为什么会这样以及如何解决这个问题?除了将所有内容投射到Int64

【问题讨论】:

标签: c# math int


【解决方案1】:

默认情况下,C# 算术是在未经检查的上下文中完成的,这意味着值将翻转。

您可以使用checked and unchecked keywords 来控制该行为。

【讨论】:

  • 刚刚遇到了 int.maxvalue + 1 是 int.minvalue 的场景……我一直在用力挠头,直到意识到它一定会翻身!
【解决方案2】:

你必须要求它:

checked {
    int a = int.MaxValue;
    int b = int.MaxValue;
    int c = a * b;    // kaboom
}

【讨论】:

    【解决方案3】:

    因为 int32 将结果限制为 32 位。

    所以,如果您在字节级别查看数学。

    FFFFFFFF * FFFFFFFF = FFFFFFFE00000001
    

    如您所见,最低的 4 个字节 = 1。

    【讨论】:

      【解决方案4】:

      您已禁用项目中的溢出检查。在选中模式打开时会抛出异常。

      【讨论】:

      • 感谢您的回复!我没有禁用溢出检查; Visual Studio 中的这个设置在哪里?
      • 我这里没有 VS 的副本,但如果我没记错的话,它在高级编译器选项中(右键单击项目,然后属性 -> 构建 -> 高级)
      【解决方案5】:

      Int32.MaxValue(使用给定的值 here)是 2,147,483,647。

      以 2 为底,即:111 1111 1111 1111 1111 1111 1111 1111... 2^31-1。第一位是符号位。

      如果你把它自己相乘,你会得到:11 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0001

      回到最初的问题“为什么是 1?”,因为 Integer.MaxValue 是最大值,导致整数溢出。结果被截断为最低 31 位,即全 0 加 1。

      编辑:这是关于二进制乘法的a tutorial。使用全 1 的简单情况: 111 * 111

      你会得到: 00111 01110 + 11100 = 100001

      对于 Int32.MaxValue 的情况,您可以扩展它。为简洁起见,我将其缩短为 3 位数。

      另外,正如另一个答案所说,在 C# 中,这些溢出将默认发生。

      【讨论】:

      • 对需要它的人来说是一种很好的治疗方法,但 OP 想知道为什么 C# 没有捕获它并抛出错误。
      【解决方案6】:

      有趣的是,无论您使用哪种底座,这都有效:

      (n-1)*(n-1)  mod n 
      n^2 - 2n + 1 mod n
      0   -  0 + 1 mod n
                 1 mod n
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-16
        • 1970-01-01
        相关资源
        最近更新 更多