簡體   English   中英

最快的方法來對數字中的數字求和

[英]Fastest way to sum digits in a number

給定一個很大的數字,例如9223372036854775807Int64.MaxValue ),對數字求和的最快方法是什么?

目前我將Toctringing並將每個char重新分解為一個int

num.ToString().Sum(c => int.Parse(new String(new char[] { c })));

這肯定是非常無懈可擊的。 有什么建議么?

最后,你將如何使用BigInteger進行這項工作?

謝謝

那么,另一種選擇是:

int sum = 0;
while (value != 0)
{
    int remainder;
    value = Math.DivRem(value, 10, out remainder);
    sum += remainder;
}

BigInteger也有一個DivRem方法,所以你可以使用相同的方法。

請注意,我已經看到DivRem沒有像“手動”那樣快地執行相同的算術,所以如果你真的對速度感興趣,你可能想要考慮一下。

還要考慮一個查找表,其中包含(例如)預先計算了總和的1000個元素:

int sum = 0;
while (value != 0)
{
    int remainder;
    value = Math.DivRem(value, 1000, out remainder);
    sum += lookupTable[remainder];
}

這意味着迭代次數減少,但每次迭代都有一個增加的數組訪問權限......

沒有人討論過BigInteger版本。 為此,我想看看10 1,10 2,10 4,10 8,以此類推,直到找到最后10 2 N小於你的價值。 取你的數字div和mod 10 2 n得出2個較小的值。 洗凈,沖洗並遞歸重復。 (你應該在一個數組中保留10的迭代方塊,並在遞歸部分傳遞有關下一個要使用的功率的信息。)

對於具有k個數字的BigInteger,除以10是O(k)。 因此,使用朴素算法求數字的總和是O(k 2 )。

我不知道C#在內部使用什么,但是用於將k位乘以或除以k位整數的非天真算法在時間O(k 1.6 )或更好(大多數更好,更好) ,但有一個開銷,使他們更糟糕的“小大整數”)。 在這種情況下,准備你的初始權力列表和分裂一次需要時間O(k 1.6 )。 這給出了2個大小為O((k / 2) 1.6 )= 2 -0.6 O(k 1.6 )的問題。 在一個新的水平,你有另外2 -1.2Ø(K 1.6)工作4個問題大小O((K / 4)1.6)的。 將所有項和2的冪加起來變成一個收斂於常數的幾何級數,因此總工作量為O(k 1.6 )。

這是一個明確的勝利,如果你正在使用數千個數字的數字,那么勝利將非常非常明顯。

是的,這可能有些低效。 我可能只是重復除以10,每次加上余數。

性能優化的第一條規則:當你可以相乘時,不要分開。 以下功能將采用四位數字0-9999並按照您的要求進行操作。 中間計算大於16位。 我們將數字乘以1/10000並將結果作為Q16定點數。 然后通過乘以10並取整數部分來提取數字。

#define TEN_OVER_10000 ((1<<25)/1000 +1) // .001 Q25

int sum_digits(unsigned int n)
{
    int c;
    int sum = 0;
    n = (n * TEN_OVER_10000)>>9; // n*10/10000 Q16
    for (c=0;c<4;c++)
    {
    printf("Digit: %d\n", n>>16);
        sum += n>>16;
        n = (n & 0xffff) * 10; // next digit
    }
    return sum;
}

這可以擴展到更大的尺寸,但它很棘手。 您需要確保定點計算中的舍入始終正常。 我也做了4位數字,因此固定點乘法的中間結果不會溢出。

    Int64 BigNumber = 9223372036854775807;

    String BigNumberStr = BigNumber.ToString();
    int Sum = 0;

    foreach (Char c in BigNumberStr)
        Sum += (byte)c;

    // 48 is ascii value of zero
    // remove in one step rather than in the loop
    Sum -= 48 * BigNumberStr.Length;

而不是int.parse,為什么不從每個數字中減去'0'來獲得實際值。

請記住,'9' - '0'= 9,所以你應該能夠按照k(數字的長度)來做到這一點。 減法只是一個操作,所以不應該減慢速度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM