重现行为MAX_VALUE和MIN_VALUE [英] Reproduce behavior MAX_VALUE and MIN_VALUE

查看:208
本文介绍了重现行为MAX_VALUE和MIN_VALUE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下内容也适用于其他 MIN_VALUE MAX_VALUE ,但我们只关注现在整数。我知道在Java中整数是32位, Integer.MAX_VALUE = 2147483647 (2 31 -1)和 Integer.MIN_VALUE = -2147483648 ( - 2 31 )。当你超出它们的界限时使用这些值计算时,数字会回绕/溢出。因此,当您执行类似 Integer.MAX_VALUE + 1 的操作时,结果与 Integer.MIN_VALUE 相同。

The following also applied to other MIN_VALUE and MAX_VALUE, but let's only focus on Integer for now. I know that in Java integers are 32-bit, with Integer.MAX_VALUE = 2147483647 (231-1) and Integer.MIN_VALUE = -2147483648 (-231). When calculating with these values when you go beyond their bounds, the number wraps around / overflows. So when you do something like Integer.MAX_VALUE + 1, the result is the same as Integer.MIN_VALUE.

以下是 MIN_VALUE MAX_VALUE 的基本算术计算:

Here are some basic arithmetic calculations with MIN_VALUE and 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

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

我的问题是:如何重现所有基本算术运算( + - * / )上面手动?

My question is: how can I reproduce all basic arithmetic operations (+-*/) above manually?

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

The first thing that came to mind was the modulo operator. So I tried a simple method like this:

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

这对大多数人来说都是正确的,但不是全部。 (为了减少这个问题的大小, 这里是一个带有测试代码的TIO链接 ,而不是这里的复制粘贴。)那些不正确的:

Which is correct for most of them, but not all. (To reduce the question size, here is a TIO link with test code, instead of a copy-paste here.) The ones that are incorrect:

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 方法,以便为所有人提供正确的结果基本算术计算(忽略Power,Modulo,Root等计算现在)?

我知道我应该在大多数情况下看看逐位操作数,但是如果没有逐位操作数,只能使用基本算术操作数(包括模数)来重现这种行为吗?

How can I modify the reproduceMinMaxFromLongToInt method so it gives the correct result for all basic arithmetic calculations (ignoring calculations like Power, Modulo, Root, and such for now)?
I know I should probably look at bit-wise operands for the most part, but is it possible to reproduce this behavior without bit-wise operands, using basic arithmetic operands (including modulo) only?

编辑:注意: Integer 仅用作示例。在这种情况下,我当然可以转换为 int 。但我正在试图找出更通用的算法,它也应用于其他 min / max ,如分钟= -100;例如,max = 99

Note: The Integer is just used as an example. Of course I could just cast to int in this case. But I'm trying to figure out the more general algorithm which also applied to other min/max, like min=-100; max=99 for example.

推荐答案

这是没有按位操作的一个(我不算数恒定生成,它们可以被写出但它会模糊它们的含义)或演员表,因为你可以看到它比应该更复杂,如果没有Java 8它会更糟:

Here's one without bitwise operations (I'm not counting the constant-generation, they could be written out but it would obscure their meaning) or casts, as you can see it's more complicated than it should be, and it would be worse without 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);
}






实施其他对最小值/ max这种方式可能是一件奇怪的事情。一种更合理的方法可能是仅使用正数(以Java为单位)模拟范围的长度,并将它们的上限范围解释为负数。


Implementing other pairs of min/max this way is probably a strange thing to do. A more reasonable approach, probably, is to work only with positive numbers (in Java) modulo the length of the range, and interpret the upper range of them as being negative.

例如,如果范围是-2到2,你可以通过以模数(实际模数,而不是Java风格的余数)映射它们将它们全部带入0..4。然后通常的mod-5算法将合理地起作用。最后只需将它们映射回原始范围,将4解释为-1(即,在mod-5算术中,这是合理的说法),将3解释为-2。

For example if the range was -2 through 2, you could bring them all into 0..4 by mapping them modulo (actual modulo, not Java-style remainder) 5. Then the usual mod-5 arithmetic will act reasonably. In the end just map them back to the original range, by interpreting 4 as -1 (which is, in mod-5 arithmetic, a reasonable thing to say) and 3 as -2.

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

You could interpret the code above as doing that, but there is the weird issue that (due to the range involved) it had to work with signed numbers as if they were unsigned, so Long.remainderUnsigned made an appearance. For small ranges that wouldn't be a problem.

这篇关于重现行为MAX_VALUE和MIN_VALUE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆