检查两个双打是否有相同标志的快速方法?假设两个双打不能为0。
答案 0 :(得分:7)
潜在解决方案:
a*b > 0
:一次浮点乘法和一次比较。(a>0) == (b>0)
:三次比较。Math.Sign(a) == Math.Sign(b)
:两个函数调用和一个比较。速度比较:
这是关于你期望的(参见底部的实验设置):
a*b > 0
:0.42±0.02s (a>0) == (b>0)
:0.49±0.01s Math.Sign(a) == Math.Sign(b)
:1.11±0.9s 重要说明:
如评论中greybeard所述,如果值乘以小于Double.Epsilon
的值,方法1很容易出现问题。除非你能保证倍数总是大于这个,否则你应该选择方法2。
实验设置:
以下代码在http://rextester.com/上运行了16次。
public static void Main(string[] args)
{
double a = 1e-273;
double b = a;
bool equiv = false;
for(int i=0; i<100000000; ++i) {
equiv = THE_COMPARISON;
b += a;
}
//Your code goes here
Console.WriteLine(equiv);
}
答案 1 :(得分:1)
您可以使用:
if (copysign(x, y) == x)
答案 2 :(得分:1)
我所知道的this comment最简单,最快捷的方法就是在两个数字的 MSB 位上使用XOR
。这是一个小的 C#示例(注意内联以避免函数开销):
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static bool fpu_cmpsign(double a, double b)
{
byte* aa;
byte* bb;
aa = (byte*)(&a); // points to the a as 8bit integral type
bb = (byte*)(&b); // points to the b as 8bit integral type
return ((aa[7] ^ bb[7]) & 128) != 128;
}
+/-
数字组合的结果:
a b result
- - 1
- + 0
+ - 0
+ + 1
这个想法很简单。该符号存储在最高位( MSB ),XOR
返回1
非等位,因此XOR
MSB 摊位号码在一起,否定了输出。 [7]
只是访问BYTE
的最高double
为8位整数类型,因此我可以使用 CPU ALU 而不是 FPU 。如果您的平台的顺序为BYTES
,则使用[0]
代替( MSB 首先是 LSB 首先是yte)。
所以你需要的只是3x 8位XOR
用于比较和否定,1x 8位AND
用于提取符号位结果。
您可以使用联合而不是指针,并使用本机位宽为您的平台获得最佳性能。