繁体   English   中英

在C#中获取数字部分值的最快方法是什么?

[英]What's the fastest way to get the partial value of a number in C#?

float f = 5.13;
double d = 5.13;

float fp = f - (float)Math.floor(f);
double dp = d - Math.floor(d);

有没有比每次调用外部函数更快的方法?

“外部功能”?

System.Math内置于mscorlib中!

这实际上是最快的方法。

您可以将f转换为int,这将修剪小数部分。 这假设您的双打属于整数范围。

当然,抖动可能足够聪明,可以将Math.floor优化为一些内联的asm,它可以比执行转换更快,然后转换为浮动。

您是否真的已经测量并验证了Math.floor的性能是否会影响您的程序? 如果还没有,在你知道这是一个问题之前,你不应该为这个级别的微优化而烦恼,然后根据原始代码测量这个替代方案的性能。

编辑:这看起来更快。 使用Math.Floor()时,以下代码需要717ms,在发布模式下,我的机器上的int cast代码需要172 ms。 但同样,我怀疑性能提升真的很重要 - 为了让这个可以测量我必须进行100米迭代。 此外,我发现Math.Floor()更具可读性和明显意图,未来的CLR可以为Math.Floor发出更优化的代码,并轻松击败这种方法。

    private static double Floor1Test()
    {
        // Keep track of results in total so ops aren't optimized away.
        double total = 0;
        for (int i = 0; i < 100000000; i++)
        {
            float f = 5.13f;
            double d = 5.13;
            float fp = f - (float)Math.Floor(f);
            double dp = d - (float)Math.Floor(d);
            total = fp + dp;
        }

        return total;
    }

    private static double Floor2Test()
    {
        // Keep track of total so ops aren't optimized away.
        double total = 0;
        for (int i = 0; i < 100000000; i++)
        {
            float f = 5.13f;
            double d = 5.13;
            float fp = f - (int)(f);
            double dp = d - (int)(d);
            total = fp + dp;
        }

        return total;
    }

    static void Main(string[] args)
    {
        System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();

        // Unused run first, guarantee code is JIT'd.
        timer.Start();
        Floor1Test();
        Floor2Test();
        timer.Stop();

        timer.Reset();
        timer.Start();
        Floor1Test();
        timer.Stop();
        long floor1time = timer.ElapsedMilliseconds;

        timer.Reset();
        timer.Start();
        Floor2Test();
        timer.Stop();

        long floor2time = timer.ElapsedMilliseconds;

        Console.WriteLine("Floor 1 - {0} ms", floor1time);
        Console.WriteLine("Floor 2 - {0} ms", floor2time);
    }
}

Donald E. Knuth说:

“我们应该忘记小的效率,比如大约97%的时间:过早的优化是所有邪恶的根源。”

因此,除非您对应用程序进行基准测试并发现此操作是瓶颈的正面证据,否则不要费心优化这些代码。

嗯,我怀疑你会获得任何真实的世界性能增益,但根据Reflector Math.Floor是这样的:

public static decimal Floor(decimal d)
{
    return decimal.Floor(d);
}

所以可以说

double dp = d - decimal.Floor(d);

可能会更快。 (编译器优化使我知道的整点意义不大......)


对于那些可能有兴趣将其带入其逻辑结论十进制的人。地板是:

public static decimal Floor(decimal d)
{
    decimal result = 0M;
    FCallFloor(ref result, d);
    return result;
}

FCallFloor是对非托管代码的调用,因此您几乎处于“优化”的极限。

Decimal的情况下,我建议忽略大家不要改变它并尝试使用Decimal.Truncate 无论是否更快,它都是专门针对您要做的事情的功能,因此更清晰一点。

哦,顺便说一句,它更快:

        System.Diagnostics.Stopwatch foo = new System.Diagnostics.Stopwatch();

        Decimal x = 1.5M;
        Decimal y = 1;
        int tests = 1000000;
        foo.Start();
        for (int z = 0; z < tests; ++z)
        {
            y = x - Decimal.Truncate(x);
        }
        foo.Stop();
        Console.WriteLine(foo.ElapsedMilliseconds);

        foo.Reset();
        foo.Start();
        for (int z = 0; z < tests; ++z)
        {
            y = x - Math.Floor(x);
        }
        foo.Stop();
        Console.WriteLine(foo.ElapsedMilliseconds);
        Console.ReadKey();

//Output: 123
//Output: 164

编辑:修正了我的解释和代码。

它是静态的,所以这应该非常快,没有任何目标可以站起来。 您可以随时进行数学水平计算,但除非您有一些认真使用该功能。 可能floor()方法已经这样做了,但如果你需要非常快的东西,你可以内联它并删除支票等,但在C#中这不是你最大的性能问题。

暂无
暂无

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

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