我知道,Int32.MaxValue * Int32.MaxValue
会产生一个大于Int32
的数字;但是,这句话不应该引发某种例外吗?
我做IF (X * Y > Z)
这样的事情时遇到了这个问题,其中Int32
都是X
。 Y
和X * Y
足够大,您可以从Int64
获得虚假价值。
为什么会如此以及如何解决这个问题?除了将所有内容都转换为{{1}}。
答案 0 :(得分:26)
因为int32将结果限制在32位。
所以,如果你看一下字节级的数学。
FFFFFFFF * FFFFFFFF = FFFFFFFE00000001
如您所见,最低的4个字节= 1。
答案 1 :(得分:19)
默认情况下,C#算术在未经检查的上下文中完成,这意味着值将翻转。
您可以使用checked and unchecked keywords来控制该行为。
答案 2 :(得分:8)
有趣的是,无论你使用什么基础,这都有效:
(n-1)*(n-1) mod n
n^2 - 2n + 1 mod n
0 - 0 + 1 mod n
1 mod n
答案 3 :(得分:6)
你必须要求它:
checked {
int a = int.MaxValue;
int b = int.MaxValue;
int c = a * b; // kaboom
}
答案 4 :(得分:6)
您已禁用项目中的溢出检查。使用选中模式On会抛出异常。
答案 5 :(得分:2)
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#中,这些溢出将默认发生。