如何检查零是正还是负?


77

是否可以检查afloat是正零(0.0)还是负零(-0.0)?

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


8
检查符号位(最左边的位)就足够了
装箱__l 2014年

6
确实,零既不是负数也不是正数。
Grijesh Chauhan 2014年

21
@GrijeshChauhan:从理论上讲
Mooing Duck 2014年

10
@fridge:但是问题不在于数学,而是关于Java。浮点值可能与数字之间的任何关系都是由人为设计的,并且易于泄漏;-)
史蒂夫·杰索普

3
可能是一个愚蠢的问题,但我只是想知道:为什么要区分正数0和负数0?
siegi 2014年

Answers:


80

是的,除以它。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 2014年

3
@njuffa:不确定math.copySign(1.0,x)<0.0比哪个更“容易” 1/x>0。我的意思是,两者都非常不言自明,因此无论如何您都想拥有一个功能
Niklas B.

2
@njuffa:是的,我认为您的答案有可读性问题;)我并不认为除法会很麻烦,因为反正零除法可能还是有特殊情况
Niklas B.

1
好吧,如果你们想了解它有多沉重,那就取决于。例如,标志转移与x87指令无关,但对SSE则非常有用。除法需要多长时间,范围从9(我认为?)到一百多个周期(取决于要除法的值和µarch)。任一个都可以获胜,而那只是在x86系统上。
哈罗德2014年

1
如果您只想提高效率,难道不将其转换为int并询问符号位是最佳解决方案吗?我不确定您在Java中执行此操作的效率如何,但在大多数体系结构中,只需使用OR指令后跟跳转零或跳转非零指令即可完成,并且OR通常是单周期的。但是,条件跳转成本因架构而异。
reirab 2014年

39

您可以使用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);


7

所使用的Math.min方法与Jesper提出的方法类似,但更加清楚:

private static int negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f);

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

6

当float为负数(包括-0.0-inf)时,它将使用与负整数相同的符号位。这意味着您可以将的整数表示与进行比较0,从而无需了解或计算的整数表示-0.0

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

那在可接受的答案上有一个额外的分支,但是我认为没有十六进制常量就更容易理解。

如果您的目标只是将-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
}

0

对于否定:

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

对于正面:

new Double(0.0).equals(new Double(value));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.