为啥 Int32.MaxValue * Int32.MaxValue == 1?

Posted

技术标签:

【中文标题】为啥 Int32.MaxValue * Int32.MaxValue == 1?【英文标题】: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

【问题讨论】:

这是在 unchecked 块中吗? 见***.com/questions/2363838/… 【参考方案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

【讨论】:

以上是关于为啥 Int32.MaxValue * Int32.MaxValue == 1?的主要内容,如果未能解决你的问题,请参考以下文章

Interlocked.Increment 溢出会导致 .NET 运行时损坏吗?

为啥 GetType 返回 System.Int32 而不是 Nullable<Int32>? [复制]

为啥 short int 和 int 在 32 位架构中具有相同的大小?

为啥 INT_FAST16_MAX 被定义为 INT32_MAX (VS 2015)?

由于缓存,为啥访问 int8_t 数组并不比 int32_t 快?

在C语言中,int类型存储的最大的数是2^32,为啥?为啥不是2^31