Kev*_*sen 5 java integer integer-overflow max min
以下内容也适用于其他MIN_VALUE和,但我们现在MAX_VALUE只关注。Integer我知道在Java中整数是32位的,有Integer.MAX_VALUE = 2147483647(2 31 -1)和Integer.MIN_VALUE = -2147483648(-2 31 )。当使用这些值进行计算时,当超出其范围时,数字会环绕/溢出。因此,当您执行类似操作时Integer.MAX_VALUE + 1,结果与 相同Integer.MIN_VALUE。
MIN_VALUE以下是使用和 进行的一些基本算术计算MAX_VALUE:
Integer.MAX_VALUE: 2147483647
Integer.MAX_VALUE + 1: -2147483648
Integer.MAX_VALUE - 1: 2147483646
Integer.MAX_VALUE * 2: -2
Integer.MAX_VALUE * 3: 2147483645
Integer.MAX_VALUE * 4: -4
Integer.MAX_VALUE * 5: 2147483643
Integer.MAX_VALUE / Integer.MAX_VALUE: 1
Integer.MAX_VALUE * Integer.MAX_VALUE: 1
Integer.MAX_VALUE / Integer.MIN_VALUE: 0
Integer.MAX_VALUE * Integer.MIN_VALUE: -2147483648
Integer.MAX_VALUE - Integer.MIN_VALUE: -1
Integer.MAX_VALUE + Integer.MIN_VALUE: -1
-Integer.MAX_VALUE: -2147483647
-Integer.MAX_VALUE - 1: -2147483648
-Integer.MAX_VALUE + 1: -2147483646
Integer.MIN_VALUE: -2147483648
Integer.MIN_VALUE + 1: -2147483647
Integer.MIN_VALUE - 1: 2147483647
Integer.MIN_VALUE * 2: 0
Integer.MIN_VALUE * 3: -2147483648
Integer.MIN_VALUE * 4: 0
Integer.MIN_VALUE * 5: -2147483648
Integer.MIN_VALUE / Integer.MAX_VALUE: -1
Integer.MIN_VALUE / Integer.MIN_VALUE: 1
Integer.MIN_VALUE * Integer.MIN_VALUE: 0
Integer.MIN_VALUE - Integer.MAX_VALUE: 1
-Integer.MIN_VALUE: -2147483648
-Integer.MIN_VALUE - 1: 2147483647
-Integer.MIN_VALUE + 1: -2147483647
Run Code Online (Sandbox Code Playgroud)
或者更一般地说(iff MIN == -MAX-1):
MAX: MAX
MAX + 1: MIN
MAX - 1: MAX - 1
MAX * 2: -2
MAX * 3: MAX - 2
MAX * 4: -4
MAX * 5: MAX - 4
MAX / MAX: 1
MAX * MAX: 1
MAX / MIN: 0
MAX * MIN: MIN
MAX - MIN: -1
MAX + MIN: -1
-MAX: MIN + 1
-MAX - 1: MIN
-MAX + 1 MIN + 2
MIN: MIN
MIN + 1: MIN + 1
MIN - 1: MAX
MIN * 2: 0
MIN * 3: MIN
MIN * 4: 0
MIN * 5: MIN
MIN / MAX: -1
MIN / MIN: 1
MIN * MIN: 0
MIN - MAX: 1
-MIN: MIN
-MIN - 1: MAX
-MIN + 1: MIN + 1
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何+-*/手动重现上面所有基本算术运算()?
我首先想到的是模运算符。所以我尝试了一个简单的方法,如下所示:
long reproduceMinMaxFromLongToInt(long n){
if(n > 2147483647L){
return n % 2147483648L;
}
if(n < -2147483648L){
return n % -2147483648L;
}
return n;
}
Run Code Online (Sandbox Code Playgroud)
这对大多数人来说是正确的,但不是全部。(为了减少问题的大小,这里有一个带有测试代码的 TIO 链接,而不是复制粘贴在这里。)不正确的:
Calculation: Should be But is instead
MAX_VALUE + 1: -2147483648 0
MAX_VALUE * 2: -2 2147483646
MAX_VALUE * 4: -4 2147483644
MAX_VALUE * MIN_VALUE: -2147483648 0
MAX_VALUE - MIN_VALUE: -1 2147483647
MIN_VALUE - 1: 2147483647 -1
MIN_VALUE * 3: -2147483648 0
MIN_VALUE * 5: -2147483648 0
-MIN_VALUE - 1: 2147483647 2147483647
Run Code Online (Sandbox Code Playgroud)
其他人都是正确的。
如何修改该reproduceMinMaxFromLongToInt方法,以便为所有基本算术计算提供正确的结果(暂时忽略幂、模、根等计算)?
我知道我可能应该在大部分情况下查看按位操作数,但是是否可以在没有按位操作数的情况下仅使用基本算术操作数(包括模数)来重现此行为?
编辑:注意:Integer仅用作示例。当然,int在这种情况下我可以直接投射到。但我试图找出也适用于其他min/的更通用的算法max,例如min=-100; max=99。
这是一个没有按位运算(我没有计算常量生成,它们可以写出来,但这会掩盖它们的含义)或强制转换,正如你所看到的,它比应有的更复杂,如果没有 Java,情况会更糟8:
long reproduceMinMaxFromLongToInt(long n){
// reduce range
n = Long.remainderUnsigned(n, 1L << 32);
// sign-extend
if (n < (1L << 31))
return n;
else
return n - (1L << 32);
}
Run Code Online (Sandbox Code Playgroud)
以这种方式实现其他对的最小/最大可能是一件奇怪的事情。更合理的方法可能是仅使用以范围长度为模的正数(在 Java 中),并将它们的上限解释为负数。
例如,如果范围是 -2 到 2,您可以通过将它们映射为模(实际模,而不是 Java 风格的余数)5,将它们全部变为 0..4。然后通常的 mod-5 算术将合理地起作用。最后只需将它们映射回原始范围,将 4 解释为 -1(在 mod-5 算术中,这是一个合理的说法)并将 3 解释为 -2。
您可以将上面的代码解释为这样做,但是有一个奇怪的问题(由于涉及的范围)它必须像无符号一样处理带符号的数字,因此Long.remainderUnsigned出现了。对于小范围来说这不是问题。