Jon*_*eet 46
这是一个糟糕的黑客方式:
private static readonly long NegativeZeroBits =
BitConverter.DoubleToInt64Bits(-0.0);
public static bool IsNegativeZero(double x)
{
return BitConverter.DoubleToInt64Bits(x) == NegativeZeroBits;
}
Run Code Online (Sandbox Code Playgroud)
基本上,这是测试-0.0的确切位模式,但无需对其进行硬编码.
Cha*_*ion 14
经过一些搜索后,我终于进入了C#规范的7.7.2节,并提出了这个解决方案.
private static bool IsNegativeZero(double x)
{
return x == 0.0 && double.IsNegativeInfinity(1.0 / x);
}
Run Code Online (Sandbox Code Playgroud)
负零具有符号位设置.从而:
public static bool IsNegativeZero(double value) {
if (value != 0) return false;
int index = BitConverter.IsLittleEndian ? 7 : 0;
return BitConverter.GetBytes(value)[index] == 0x80;
}
Run Code Online (Sandbox Code Playgroud)
编辑:正如OP指出的那样,这在发布模式下不起作用.x86 JIT优化器严重接受if()语句并直接加载零而不是加载值.这确实更高效.但这会导致负零丢失.需要对代码进行解调以防止这种情况:
public static bool IsNegativeZero(double value) {
int index = BitConverter.IsLittleEndian ? 7 : 0;
if (BitConverter.GetBytes(value)[index] != 0x80) return false;
return value == 0;
}
Run Code Online (Sandbox Code Playgroud)
这是x86抖动的典型行为btw,它在优化浮点代码时不能很好地处理极端情况.在这方面,x64抖动要好得多.虽然可以说没有比给负零的意义更糟糕的角落情况.预先警告.
这是另一个黑客.它利用了一个事实,即Equals
在一个struct
遗嘱上做一个按位比较,而不是调用Equals
它的成员:
struct Negative0
{
double val;
public static bool Equals(double d)
{
return new Negative0 { val = -0d }.Equals(new Negative0 { val = d });
}
}
Run Code Online (Sandbox Code Playgroud)
Negative0.Equals(0); // false
Negative0.Equals(-0.0); // true