对一个很长的二进制数的数字求和

本文关键字:二进制数 数字 求和 一个 | 更新日期: 2023-09-27 18:11:18

朋友问我:

如果是2^10 = 1024,我们可以取1024并拆分并总结其数字:

1+0+2+4 = 7.

这很简单。

然而,当输入是2^30000(输入实际上是一个长字符串"1000...")——没有。net类型可以保存这个值。

所以必须有一个技巧来求和它的数字(十进制值的数字)....

编辑:

相关技巧(用于查找10^20 - 16)

100 = 10^2(1和两个0)

10^20 =(1和20个零)

因此

:

10^20 - 16 = 18个9,一个8和4。

18*9+8+4 = 174

但是我还没有成功地将这个解决方案转化为我的问题。(我试了很多次)。

*我标记这个问题为。net,因为我可以使用字符串函数,数学函数从。net库。*

这里有什么技巧可以让我把x^n的结果加起来吗?

这里的诀窍是什么?

编辑#2:添加了。net2标签(其中biginteger不可用)-我想知道我如何能做到没有biginteger。(我正在寻找隐藏的技巧)

对一个很长的二进制数的数字求和

您可以利用BigInteger结构来做到这一点。就像MSDN

里写的那样

BigInteger类型是一个不可变的类型,表示一个任意大的整数,其值在理论上没有上限或下限界限。

基本上在创建BigInteger实例并计算指数之后,你可以将其转换为字符串。之后,您将遍历该字符串的每个字符并将每个字符转换为int number。把所有的整型数加起来,你就会得到答案。

BigInteger bi = new BigInteger(2);
var bi2 = BigInteger.Pow(bi, 30000);
BigInteger sum = new BigInteger();
foreach(var ch in bi2.ToString())
    sum = BigInteger.Add(sum, new BigInteger(int.Parse(ch.ToString())));
MessageBox.Show(bi2.ToString() + " - " + sum.ToString());

对于找到一个数字的以10为基数的和,我不知道一般的技巧。

然而,有一个简单的技巧可以找到一个数的 10位根

数字和,就像你说的,就是所有数字的和。1024的十进制数和是1 + 2 + 4 = 7。65536的十进制和是6 + 5 + 5 + 3 + 6 = 25。

数字根是当你重复数字和直到只有一个数字时得到的。65536的数字和是25,所以数字根是2 + 5 = 7。

诀窍是:如果你有Z = X * Y,那么DigitRoot(Z) = DigitRoot(DigitRoot(X) * DigitRoot(Y))。(给读者的练习:证明它!提示:从证明加法的相同恒等式开始。

如果你有一个容易分解的数字-最容易分解的数字是2n -然后很容易递归地计算出数字根:216 = 28 * 28,所以DigitRoot(216) = DigitRoot(DigitRoot(28)) -我们只是把问题变小了。现在我们不需要计算216,我们只需要计算28。你当然可以用230000——把它分解成DigitRoot(DigitRoot(215000 * DigitRoot(215000)))。如果215000太大,则进一步分解;不断分解,直到你有一个足够小的问题可以解决。

有意义吗?

我不相信这里有什么诀窍。您展示的后一种技巧是有效的,因为数字和结果都是十进制数。

For example:
1267 = 1*10^3 + 2*10^2 + 6*10^1 + 7*10^0

所以幂和之间有明显的关联。但不幸的是,如果你想把二进制数,或者2的幂,转换成十进制数,这是行不通的。最好的办法是减少功率来增加基数。

2^3000 = 4^1500 = 16^750 = 256^375

但如你所见,数列跳过以10为底。可悲的是,这意味着你需要将最终结果计算为十进制数,然后才能将其转换为10的幂。

From http://blog.singhanuvrat.com/problems/sum-of-digits-in-ab:

public class Problem_16 {
    public long sumOfDigits(int base, int exp) {
        int numberOfDigits = (int) Math.ceil(exp * Math.log10(base));
        int[] digits = new int[numberOfDigits];
        digits[0] = base;
        int currentExp = 1;
        while (currentExp < exp) {
            currentExp++;
            int carry = 0;
            for (int i = 0; i < digits.length; i++) {
                int num = base * digits[i] + carry;
                digits[i] = num % 10;
                carry = num / 10;
            }
        }
        long sum = 0;
        for (int digit : digits)
            sum += digit;
        return sum;
    }
    public static void main(String[] args) {
        int base = 2;
        int exp = 3000;
        System.out.println(new Problem_16().sumOfDigits(base, exp));
    }
}
c#

public class Problem_16 {
    public long sumOfDigits(int base1, int exp) {
        int numberOfDigits = (int) Math.Ceiling(exp * Math.Log10(base1));
        int[] digits = new int[numberOfDigits];
        digits[0] = base1;
        int currentExp = 1;
        while (currentExp < exp) {
            currentExp++;
            int carry = 0;
            for (int i = 0; i < digits.Length; i++) {
                int num = base1 * digits[i] + carry;
                digits[i] = num % 10;
                carry = num / 10;
            }
        }
        long sum = 0;
        foreach (int digit in  digits)
            sum += digit;
        return sum;
    }
}

void Main()
{
     int base1 = 2;
        int exp = 3000000;
        Console.WriteLine (new Problem_16().sumOfDigits(base1, exp));
}