简体   繁体   English

在 C# 中离散化双精度的最快方法是什么?

[英]What is the fastest way to discretize double in C#?

I have a double between -1 and 1.我有一个介于 -1 和 1 之间的双精度值。

I need to discretize it by N steps it really, really fast.我需要将它离散化 N 步,它非常非常快。 If N is 5 my end values would be one of these:如果 N 为 5,我的最终值将是以下之一:

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

I need a function:我需要一个 function:

double discretize(double value)

so that for example:例如:

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

I wonder if there's any trick with the mantissa/exponent, to make it discrete with bit shifts etc... without making any floating-point arithmetics.我想知道尾数/指数是否有任何技巧,通过位移等使其离散......而不进行任何浮点运算。

Sounds like a rounding operation.听起来像一个舍入操作。

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;
    }
}

with the program output使用程序 output

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. PS。 Since you are doing division after the round it might better to use the ToEven option由于您在回合后进行除法,因此最好使用ToEven选项

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

If you want fast speed then switch from double to float and use the functions in System.Numerics to load multiple values in vectors.如果您想要更快的速度,请从double切换到float ,并使用System.Numerics中的函数在向量中加载多个值。

Also decorate the functions with aggressive inlining which in turn has a better chance to produce vectorized code by the JIT.还使用积极的内联来装饰函数,这反过来有更好的机会通过 JIT 生成矢量化代码。

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

Finally, consider doing this math processing with C++ or even better Fortran (maybe even Julia) using a library.最后,考虑使用库使用 C++ 甚至更好的 Fortran(甚至可能是 Julia)进行此数学处理。

Fastest method so far:迄今为止最快的方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM