代码之家  ›  专栏  ›  技术社区  ›  Kevin Cruijssen

再现行为最大值和最小值

  •  4
  • Kevin Cruijssen  · 技术社区  · 7 年前

    MIN_VALUE MAX_VALUE ,但我们只关注 Integer 现在。我知道在Java中,整数是32位的 Integer.MAX_VALUE = 2147483647 (2 -1) 和 Integer.MIN_VALUE = -2147483648 (-2 ). 当您使用这些值进行计算时,当您超出其界限时,数字会环绕/溢出。所以当你做这样的事情时 Integer.MAX_VALUE + 1 ,结果与 Integer.MIN_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
    

    或更多(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
    

    +-*/ )是否手动执行以上操作?

    首先想到的是模算子。所以我尝试了这样一种简单的方法:

    long reproduceMinMaxFromLongToInt(long n){
      if(n > 2147483647L){
        return n % 2147483648L;
      }
      if(n < -2147483648L){
        return n % -2147483648L;
      }
      return n;
    }
    

    这对大多数人来说是正确的,但不是所有人。(为了减少问题量, here is a TIO link

    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
    

    其他人是正确的。

    如何修改 reproduceMinMaxFromLongToInt 方法,因此它为所有基本算术计算提供了正确的结果(暂时忽略幂、模、根等计算)?

    整数 只是作为一个例子。当然我可以投 int min / max min=-100; max=99 例如

    2 回复  |  直到 7 年前
        1
  •  1
  •   user555045    7 年前

    这里有一个没有按位运算(我不算常数生成,它们可以写出来,但会模糊其含义)或强制转换,正如你所看到的,它比应该的更复杂,如果没有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);
    }
    

    以这种方式实现其他最小/最大对可能是一件奇怪的事情。一种更合理的方法可能是只处理正数(在Java中)对范围长度的模,并将其上限解释为负数。

    例如,如果范围为-2到2,则可以将它们全部置为0。。4通过将它们映射为模(实际的模,而不是Java风格的余数)5。然后,通常的mod-5算法将合理运行。最后,通过将4解释为-1(在mod-5算法中,这是一个合理的说法)和3解释为-2,将它们映射回原始范围。

    您可以将上面的代码解释为这样做,但有一个奇怪的问题(由于涉及的范围),它必须像处理无符号数字一样处理有符号数字,所以 Long.remainderUnsigned 出现了。对于小范围,这不会是一个问题。

        2
  •  0
  •   Horia Coman    7 年前

    一个解决方案是将数字转换为 int long 遵守你的方法合同。