簡體   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