为啥 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)
之类的操作时遇到了这个问题,所有这些都是Int32
。 X
和 Y
足够大,你从 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)?