java浮点数相等_Java浮点数相等性的判断

Java浮点数相等性的判断

问题描述如下:

给定两个变量double a、double b,它们对应的装箱类型变量分别是Double x、Double y,问:

是否存在一组a、b、x、y,满足 a==b && !x.equals(y) ?

是否存在一组a、b、x、y,满足 a!=b && x.equals(y) ?

乍看之下似乎是不可能的,实际上确实存在这样的值,参考以下代码

public static void main() {

double a = 0.0;

double b = -0.0;

double c = Double.NaN;

double d = Double.NaN;

Double x = a;

Double y = b;

Double z = c;

Double w = d;

System.out.println(a == b); //输出true

System.out.println(x.equals(y)); //输出false

System.out.println(c == d); //输出false

System.out.println(w.equals(z)); //输出true

}

Double类型equals方法的实现和 ==操作符逻辑有所不同。

先看==操作符,以Java8为例,根据Java语言规范15.21.1,对于浮点数相等性判断,遵从IEEE 754规范:

只要有一个操作数是NaN,==表达式的结果总是false,!=表达式的结果总是true。实际上,当且仅当x的值为NaN时,表达式 x!=x 为真。可以使用Float.NaN方法或者Double.NaN方法判断一个值是否是NaN。

正数0与负数0相等,例如表达式 0.0==-0.0 为真。

除此之外,两个不同的浮点数使用==或!=操作符判断相等性时,会认为它们不相等。尤其是,一个值表示正无穷,一个值表示负无穷;如果它们与自身比较,是相等的;与其他值比较,是不相等的。

再看JDK中Double的equals方法实现:

public boolean equals(Object obj) {

return (obj instanceof Double)

&& (doubleToLongBits(((Double)obj).value) ==

doubleToLongBits(value));

}

/**

* Returns a representation of the specified floating-point value

* according to the IEEE 754 floating-point "double

* format" bit layout.

*

*

Bit 63 (the bit that is selected by the mask

* {@code 0x8000000000000000L}) represents the sign of the

* floating-point number. Bits

* 62-52 (the bits that are selected by the mask

* {@code 0x7ff0000000000000L}) represent the exponent. Bits 51-0

* (the bits that are selected by the mask

* {@code 0x000fffffffffffffL}) represent the significand

* (sometimes called the mantissa) of the floating-point number.

*

*

If the argument is positive infinity, the result is

* {@code 0x7ff0000000000000L}.

*

*

If the argument is negative infinity, the result is

* {@code 0xfff0000000000000L}.

*

*

If the argument is NaN, the result is

* {@code 0x7ff8000000000000L}.

*

*

In all cases, the result is a {@code long} integer that, when

* given to the {@link #longBitsToDouble(long)} method, will produce a

* floating-point value the same as the argument to

* {@code doubleToLongBits} (except all NaN values are

* collapsed to a single "canonical" NaN value).

*

* @param value a {@code double} precision floating-point number.

* @return the bits that represent the floating-point number.

*/

public static long doubleToLongBits(double value) {

long result = doubleToRawLongBits(value);

// Check for NaN based on values of bit fields, maximum

// exponent and nonzero significand.

if ( ((result & DoubleConsts.EXP_BIT_MASK) ==

DoubleConsts.EXP_BIT_MASK) &&

(result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)

result = 0x7ff8000000000000L;

return result;

}

Double的equals方法,通过==操作符,判断两个对象的doubleToLongBits返回值是否相等,来觉得两个对象是否相等。方法注释中有一句

If the argument is NaN, the result is 0x7ff8000000000000L

所以使用equals判断两个NaN时,结果为真。

对于其他情况,根据value的二进制表示,doubleToLongBits返回对应的long值。而0.0和-0.0的符号位不同,所以二进制表示也不同,doubleToLongBits的结果也不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值