对一个很长的二进制数的数字求和
本文关键字:二进制数 数字 求和 一个 | 更新日期: 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));
}