首页 > 解决方案 > 在 C# 中离散化双精度的最快方法是什么?

问题描述

我有一个介于 -1 和 1 之间的双精度值。

我需要将它离散化 N 步,它非常非常快。如果 N 为 5,我的最终值将是以下之一:

-1,-0.8,-0.6,-0.4,-0.2,0,0.2,0.4,0.6,0.8,1

我需要一个函数:

double discretize(double value)

例如:

discretize(0.091231) = 0
discretize(0.192312) = 0.2

我想知道尾数/指数是否有任何技巧,通过位移等使其离散......而不进行任何浮点算术。

标签: c#

解决方案


听起来像一个舍入操作。

static class Program
{
    static readonly Random rng = new Random();
    static void Main(string[] args)
    {
        for (int i = 0; i < 15; i++)
        {
            var x = rng.NextDouble();
            Debug.WriteLine($"{x,-15} = {x.Quantize(5)}");
        }
    }

    public static double Quantize(this double x, int steps)
    {
        return Math.Round(x*steps)/steps;
    }
}

与程序输出

0.45652442819277 = 0.4
0.649511796259094 = 0.6
0.605691870490877 = 0.6
0.685007393679119 = 0.6
0.489223629929695 = 0.4
0.496371834304357 = 0.4
0.153276258685289 = 0.2
0.212714763457288 = 0.2
0.0338650732458872 = 0
0.0612733452866195 = 0
0.258718123314305 = 0.2
0.906546349593693 = 1
0.39698489727312 = 0.4
0.728462797928817 = 0.8
0.140497107589849 = 0.2

PS。由于您在回合后进行除法,因此最好使用该ToEven选项

Math.Round(x*steps, MidpointRounding.ToEven)/steps

如果您想要更快的速度,请从doubleto切换float并使用 in 函数System.Numerics在向量中加载多个值。

还使用积极的内联来装饰函数,这反过来有更好的机会通过 JIT 生成矢量化代码。

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static double Quantize(this double x, int steps)
    {
        return Math.Round(x*steps)/steps;
    }

最后,考虑使用 C++ 甚至更好的 Fortran(甚至可能是 Julia)使用库来进行这种数学处理。


推荐阅读