总结一个很长的二进制数的数字?

时间:2013-04-27 07:42:20

标签: c# binary numbers .net-2.0

朋友问我:

如果2^10 = 1024,我们可以取1024并打破并汇总其数字:

1+0+2+4 = 7.

这很容易。

但是当输入为2^30000时(输入实际上是一个长字符串"1000...") - 没有.net类型可以保存此值。

所以必须有一个技巧来加总其数字(小数值的数字)....

已编辑:

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

  

100 = 10 ^ 2(一个和两个零)

     

10 ^ 20 =(1和20个零)

     

因此:

     

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

     

18 * 9 + 8 + 4 = 174

但我没有成功将此解决方案转换为我的问题。(我尝试了很多)。

*我将此问题标记为.net,因为我可以使用字符串函数,来自.net库的数学函数。*

问题

这里有什么技巧可以让我总结很多数字,这是x^n的结果吗?

这里的诀窍是什么?

编辑#2 :添加.net2标记(biginteger不可用) - 我想知道如何在没有biginteger的情况下做到这一点。(我正在寻找隐藏的技巧)

4 个答案:

答案 0 :(得分:7)

您可以利用BigInteger结构来执行此操作。因为它是用MSDN编写的

  

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

基本上在创建BigInteger实例并评估指数后,您可以将其转换为字符串。之后,您将遍历该字符串的每个字符,并将每个char转换为int数。添加所有这些int数字,你就会得到答案。

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());

答案 1 :(得分:5)

我不知道找到一个数字的基数10位数和的一般技巧。

但是,有一个简单的方法可以找到一个数字的基数10位根

正如您所说,数字总和只是所有数字的总和。 1024的基数10位是1 + 2 + 4 = 7.基数10位数和65536是6 + 5 + 5 + 3 + 6 = 25.

数字根是重复数字总和时得到的,直到只有一个数字。数字总和65536是25,因此数字根是2 + 5 = 7.

技巧是:如果你有Z = X * Y,那么DigitRoot(Z)= DigitRoot(DigitRoot(X)* DigitRoot(Y))。 (向读者练习:证明它!提示:首先证明添加相同的身份。)

如果你有一个易于分解的数字 - 并且最简单的因子是2 n - 那么很容易递归地找出数字根:2 16 = 2 8 * 2 8 ,因此DigitRoot(2 16 )= DigitRoot(DigitRoot(2 8 ) * DigitRoot(2 8 )) - 我们只是把问题变得更小了。现在我们不必计算2 16 ,我们只需要计算2 8 。您当然可以使用2 30000 - 将其分解为DigitRoot(DigitRoot(2 15000 * DigitRoot(2 15000 ))如果2 15000 太大,请将其进一步分解;继续将其分解,直到遇到足够小的问题解决。

有意义吗?

答案 2 :(得分:2)

我不相信这里可以有一招。 你显示的后一个技巧是有效的,因为数字和结果都是十进制数。

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的幂。使这个技巧无效。

答案 3 :(得分:1)

来自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));

}