更优雅的方法来确定两个花车在C#中是否有相同的标志?

时间:2018-04-14 09:37:48

标签: c# floating-point compare signed

有没有什么方法可以在C#中快速比较两个花车的迹象?我怀疑一次又一次地将浮点数与0进行比较的表现。但是,似乎在C#中禁止浮点操作,因此我们不能使用像(a ^ b)& 0x80000000或((a>>> 31)==(b>> 31))这样的方法来确定(在这里忽略0的情况)。

关于从float到int(没有指针)的转换问题是舍入的,因为每个小于1的数字都将舍入为0。

从float转换为int(带指针)的问题只有两个可能的返回值,无法识别0。

现在是时候测试预判0和使用指针的组合的表现。

(关于我在这里犯过的错误的删除)

1 个答案:

答案 0 :(得分:0)

如果您使用unsafe,您可以使用指针将这些位转换为int,然后您可以执行按位操作

*(int*)(&val1) >> 31 == *(int*)&val2 >> 31;

如果您担心性能,可以使用MethodImplOptions.AggressiveInlining

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe bool IsSameSign(float val1, float val2)
{
   return *(int*)(&val1) >> 31 == *(int*)&val2 >> 31;
}

为了您的娱乐,我针对您的原始版本做了一些基准测试。我通过100,000次比较运行每次测试50次,分别为1,000,000次

Test Framework : .NET Framework 4.7.1

Scale : 100000
Name          |       Time |     Delta |  Deviation |      Cycles
-----------------------------------------------------------------
MySameSign    |   1.045 ms |  0.052 ms |       0.20 |   3,498,252
BaseSameSign  |  15.391 ms |  0.548 ms |       0.81 |  52,181,763


Scale : 1000000
Name          |        Time |     Delta |  Deviation |       Cycles
-------------------------------------------------------------------
MySameSign    |   10.000 ms |  0.232 ms |       0.31 |   33,995,263
BaseSameSign  |  146.250 ms |  1.311 ms |       1.13 |  498,064,434 

示例数据

static float NextFloat()
{
   double mantissa = (_rand.NextDouble() * 2.0) - 1.0;
   double exponent = Math.Pow(2.0, _rand.Next(-126, 128));
   return (float)(mantissa * exponent);
}
public static List<Tuple<float,float>> GenerateSignInput(int scale)
{
   return Enumerable.Range(1, scale)
                     .Select(x => new Tuple<float, float>(NextFloat(), NextFloat()))
                     .ToList();
}