如何判断零是正数还是负数?

80

有没有可能检查一个float是否是正零(0.0)或者负零(-0.0)?

我已经将float转换成了String,并且检查了第一个char是否为'-',但是还有其他的方法吗?


8
检查符号位(最左侧的一位)就足够了。 - boxed__l
6
实际上,零既不是负数也不是正数。 - Grijesh Chauhan
22
@GrijeshChauhan:仅在理论上。 - Mooing Duck
10
@fridge:但问题并不是关于数学,而是关于Java。浮点值可能与数字相关,这是人为设计的,并容易出现泄漏的抽象化;-) - Steve Jessop
3
可能是一个愚蠢的问题,但我想知道:为什么需要区分正零和负零? - siegi
显示剩余2条评论
8个回答

81

是的,除以它。1 / +0.0f+Infinity,但是 1 / -0.0f-Infinity。使用简单比较很容易找出它是哪一个,因此您会得到:

if (1 / x > 0)
    // +0 here
else
    // -0 here

(这假设x只可能是两个零中的其中一个)


6
使用Math.copySign是否将零的符号转移到其他数字(例如1.0),会更容易一些?例如:if (math.copySign (1.0, x) < 0.0) ... - njuffa
3
不确定math.copySign(1.0,x)<0.0怎样比1/x>0更加"简单"。因为两者都不太容易理解,所以你最好使用一个专门的函数来代替它们。 - Niklas B.
2
@njuffa:是的,我认为您对这个答案的可读性有问题 ;) 我没考虑到除法会很重,因为零除数可能已经有特殊情况了。 - Niklas B.
1
如果你们想要深入了解它的重量,那就要看情况而定。例如,使用x87指令进行符号传输很麻烦,但使用SSE则非常好。至于长除法需要多长时间,这取决于被除数和µarch的值,范围从9(我想是这样?)到一百多个周期不等。任何一种方法都可能获胜,这只是在x86系统上的情况。 - harold
1
如果你只想要效率,将其转换为int并查询符号位是否是最佳解决方案?我不确定在Java中你能否高效地完成这个操作,但在大多数架构上,这可以通过一个OR指令和一个跳零或跳非零指令来简单实现,而且OR通常是单周期的。然而,条件跳转的成本因架构而异。 - reirab
显示剩余3条评论

41
你可以使用 Float.floatToIntBits 将其转换为一个 int,并查看二进制模式:
float f = -0.0f;

if (Float.floatToIntBits(f) == 0x80000000) {
    System.out.println("Negative zero");
}

比起除法,这种方法更好,因为除法可能需要几个时钟周期,并且可能会在FPU单元中触发溢出条件。更好的方法是:(Float.floatToIntBits(f) & 0x80000000) < 0 - Mark Jeronimus

12

绝对不是最好的方法。请查看该函数。

Float.floatToRawIntBits(f);

Doku:

=>

文档:

/**
 * Returns a representation of the specified floating-point value
 * according to the IEEE 754 floating-point "single format" bit
 * layout, preserving Not-a-Number (NaN) values.
 *
 * <p>Bit 31 (the bit that is selected by the mask
 * {@code 0x80000000}) represents the sign of the floating-point
 * number.
 ...
 public static native int floatToRawIntBits(float value);

12

Double.equals方法在Java中区分±0.0。(还有Float.equals方法。)

我有点惊讶没有人提到这些方法,因为它们对我来说似乎比目前给出的任何方法都更清晰明了!


这确实更清晰; 但是,您可能不希望在堆上分配两个对象来仅比较两个值。 - Klitos Kyriacou

9
Math.min 的使用方法类似于 Jesper 提出的方法,但更加清晰明了。
private static int negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f);

float f = -0.0f;
boolean isNegativeZero = (Float.floatToRawIntBits(f) == negativeZeroFloatBits);

8

当一个浮点数为负数(包括-0.0-inf)时,它使用与负整数相同的符号位。这意味着您可以将整数表示与0进行比较,无需知道或计算-0.0的整数表示:

if(f == 0.0) {
  if(Float.floatToIntBits(f) < 0) {
    //negative zero
  } else {
    //positive zero
  }
}

这篇回答相对于被接受的回答多了一个分支,但我认为没有16进制常量更容易阅读。

如果你的目标只是把-0看作负数,你可以省略外部的if语句:

if(Float.floatToIntBits(f) < 0) {
  //any negative float, including -0.0 and -inf
} else {
  //any non-negative float, including +0.0, +inf, and NaN
}

1

对于负数:

new Double(-0.0).equals(new Double(value));

正向情况:

new Double(0.0).equals(new Double(value));

1

只需使用Double.compare(d1,d2)。

double d1 = -0.0;    // or d1 = 0.0

if ( Double.compare (d1, 0.0)  < 0 )
    System.out.println("negative zero");
else
    System.out.println("positive zero");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接