Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 数字中求和的最快方法_C#_Math_Sum_Digits - Fatal编程技术网

C# 数字中求和的最快方法

C# 数字中求和的最快方法,c#,math,sum,digits,C#,Math,Sum,Digits,如果数字很大,例如9223372036854775807(Int64.MaxValue),最快的求和方法是什么 目前,我正在将每个字符串入并重新划分为一个int: num.ToString().Sum(c => int.Parse(new String(new char[] { c }))); 这无疑是极其低效的。有什么建议吗 最后,您如何使用biginger 谢谢,另一个选择是: int sum = 0; while (value != 0) { int remainder;

如果数字很大,例如
9223372036854775807
Int64.MaxValue
),最快的求和方法是什么

目前,我正在将每个字符串入并重新划分为一个
int

num.ToString().Sum(c => int.Parse(new String(new char[] { c })));
这无疑是极其低效的。有什么建议吗

最后,您如何使用
biginger


谢谢,另一个选择是:

int sum = 0;
while (value != 0)
{
    int remainder;
    value = Math.DivRem(value, 10, out remainder);
    sum += remainder;
}
biginger
还有一个
DivRem
方法,因此您可以使用相同的方法

<>请注意,我已经看到<代码> DivRem 不像手动操作相同的算术一样快,所以如果你真的对速度感兴趣,你可能想考虑一下。

还考虑一个查找表,用(1000)元素计算和:

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

这将意味着更少的迭代,但每次迭代都会增加一个数组访问…

是的,这可能有点低效。我可能只是重复地除以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;
}
#定义10除以10000((19;//n*10/10000 Q16
对于(c=0;c>16);
总和+=n>>16;
n=(n&0xffff)*10;//下一位数字
}
回报金额;
}

这可以扩展到更大的大小,但它很棘手。您需要确保定点计算中的舍入始终正确。我还使用了4位数字,这样定点乘法的中间结果就不会溢出。

没有人讨论过BigInteger版本。为此,我将查看101、102、104、108等等打开,直到找到最后一个小于您的值的102n。使用数字div和mod 102n得出两个较小的值。清洗、冲洗并递归重复。(应将迭代的10平方保持在一个数组中,并在递归部分传递有关下一次使用的幂的信息。)

对于一个有k个数字的大整数,除以10就是O(k)。因此,用朴素算法求出的数字之和是O(k2)

我不知道C#在内部使用了什么,但用于将k位乘以或除以k位整数的非朴素算法都能在时间O(k1.6)或更好的情况下工作(大多数都要好得多,但对于“小-大整数”来说,它们的开销更大)在这种情况下,准备你的初始幂和分裂列表需要时间O(k1.6)。这会给你2个大小为O((k/2)1.6)=2-0.6O(k1.6)的问题。在下一个级别,你有4个大小为O((k/4)1.6)的问题,另一个2-1.2O(k1.6)功。把所有的项和2的幂加起来,变成一个收敛于常数的几何级数,所以总功是O(k1.6)


这是一个肯定的胜利,如果您使用的是数千位数的数字,那么胜利将非常明显。

为什么不从每个数字中减去“0”以获得实际值,而不是int.parse呢

    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;

记住,'9'-'0'=9,因此您应该能够按k(数字的长度)的顺序执行此操作。减法只是一个操作,因此不会减慢速度。

这称为“面值”对于一个数字,顺便说一句。我们必须允许最大值吗?如果您真正想要的是重复和,那么有一个技巧。请参阅最近的问题:再次,这是什么BigInteger.ToString()也必须这样做。很难击败,它是经过大量优化的。如果
DivRem
比手动操作慢,那它有什么好处?它不是更可读的…@configurator:很可能只是在某些情况下慢。老实说,我没有详细调查。我使用DivRem和整数除以10进行了一些测试乘以10再减去,DivRem也一样快。我也用floor测试乘以.10*10,速度会慢一些。你在开玩笑吗?不一样吗(实际上更糟)而不仅仅是将每个字符串数字转换为整数?如果您指的是Integer.parseInt,那么不是。请看一下该方法的代码。有很多错误情况等都会被处理。如果您知道您处理的是整数字符串,那么减法将比使用其他方法转换它们更快。I刚刚意识到上面的源代码是针对Java的,而不是针对C#,但是你明白了。