检查两个双打是否有相同符号的快速方法?

时间:2016-06-04 04:46:35

标签: c# algorithm performance

检查两个双打是否有相同标志的快速方法?假设两个双打不能为0。

3 个答案:

答案 0 :(得分:7)

潜在解决方案:

  1. a*b > 0:一次浮点乘法和一次比较。
  2. (a>0) == (b>0):三次比较。
  3. Math.Sign(a) == Math.Sign(b):两个函数调用和一个比较。
  4. 速度比较:

    这是关于你期望的(参见底部的实验设置):

    1. a*b > 0:0.42±0.02s
    2. (a>0) == (b>0):0.49±0.01s
    3. Math.Sign(a) == Math.Sign(b):1.11±0.9s
    4. 重要说明:

      如评论中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用于提取符号位结果。

您可以使用联合而不是指针,并使用本机位宽为您的平台获得最佳性能。