为什么Java的double/float Math.min()以这种方式实现? [英] Why is Java's double/float Math.min() implemented this way?

查看:51
本文介绍了为什么Java的double/float Math.min()以这种方式实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看 java.lang.Math 的源代码中的某些内容,并且我注意到,当 Math.min(int,int)(或它的长整数)对应对象)的实现方式是

I was looking through some things in the source of java.lang.Math, and I noticed that while Math.min(int, int) (or its long counterpart) is implemented this way:

public static int min(int a, int b) {
   return a <= b ? a : b;
}

这对我来说完全有意义,与我要做的一样.但是,double/float实现是这样的:

And this makes complete sense to me and it is the same as what I would do. However, the double/float implementation is this:

public static float min(float a, float b) {
   if (a != a) {
      return a;
   } else if (a == 0.0F && b == 0.0F && (long)Float.floatToRawIntBits(b) == negativeZeroFloatBits) {
      return b;
   } else {
      return a <= b ? a : b;
   }
}

我完全傻眼了.将 a 与自身进行比较?第二张支票还算什么?为什么它不能以与int/long版本相同的方式实现?

I'm completely dumbfounded. Comparing a to itself? What's the second check even for? Why isn't it implemented in the same way as the int/long version?

推荐答案

浮点数字比整数值复杂得多.

Floating-point numbers are way more complicated than integer values.

对于这种特定情况,有两个区别很重要:

For this specific case two distinctions are important:

  • NaN float double 的有效值,表示不是数字".并表现怪异.即,它不等于自己.
  • 浮点数可以区分0.0和-0.0.当您计算某些函数的极限时,负零可能很有用.区分极限是从正方向还是负方向接近0可能是有益的.
  • NaN is a valid value for float and double which represents "not a number" and behaves weirdly. Namely, it doesn't compare equal to itself.
  • Floating point numbers can differentiate between 0.0 and -0.0. A negative zero could conceivably be useful when you're calculating the limit of some function. Distinguishing whether a limit approaches 0 from the positive or the negative direction could be beneficial.

所以这部分:

if (a != a) {
      return a;
}

确保如果 a NaN (如果 a 不是 NaN ,但 b 是,则稍后的"normal"检查将返回 b ,即 NaN ,因此没有显式检查这种情况下需要).这是一种常见的模式:计算任何一个输入为 NaN 的内容时,输出也将为 NaN .由于 NaN 通常表示计算中的某些错误(例如,将值除以0),因此重要的是它会中毒".所有进一步的计算,以确保不会默默地吞下该错误.

ensures that NaN is returned if a is NaN (if a is not NaN, but b is, then the "normal" check later on will return b, i.e. NaN, so no explicit check is needed for this case). This is a common pattern: when calculating anything where one input is NaN, the output will also be NaN. Since NaN usually represents some error in the calculation (such as dividing a value by 0), it's important that it "poisons" all further calculations to ensure the error isn't silently swallowed.

此部分:

if (a == 0.0F && b == 0.0F && (long)Float.floatToRawIntBits(b) == negativeZeroFloatBits) {
      return b;
}

确保如果比较两个零值浮点数,并且 b 为负零,则返回负零(因为-0.0小于" 0.0).与 NaN 相似,普通检查将正确返回 a (如果它是-0.0,而 b 是0.0).

ensures that if you compare two zero-valued floating point numbers and b is negative zero then that negative zero is returned (since -0.0 is "smaller" than 0.0). Similarly to NaN the normal check will correctly return a if it's -0.0 and b is 0.0.

这篇关于为什么Java的double/float Math.min()以这种方式实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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