数字 2^1000 的数字之和是多少

本文关键字:数字 多少 1000 | 更新日期: 2023-09-27 18:34:47

这是欧拉计划的一个问题,这个问题包括一些源代码,所以如果你有兴趣自己解决它,请考虑你的剧透警报。不鼓励分发问题的解决方案,这不是我想要的。我只是真诚地在正确的方向上得到一点推动和指导。

问题如下:

2^15 = 32768,其数字之和为 3 + 2 + 7 + 6 + 8 = 26。

数字 2^1000 的数字之和是多少?

我了解问题的前提和数学原理,但我一周前才开始练习 C#,所以我的编程充其量是不稳定的。

我知道 int、long 和 double 对于精确地保存 2^1000 的 300+(以 10 为基数(数字是无可救药的,因此需要一些策略。我的策略是设置一个计算,逐个获取数字,并希望编译器能够弄清楚如何计算每个数字而不会出现溢出等错误:

using System;
using System.IO;
using System.Windows.Forms;
namespace euler016
{
    class DigitSum
    {
        // sum all the (base 10) digits of 2^powerOfTwo
        [STAThread]
        static void Main(string[] args)
        {
            int powerOfTwo = 1000;
            int sum = 0;
            // iterate through each (base 10) digit of 2^powerOfTwo, from right to left
            for (int digit = 0; Math.Pow(10, digit) < Math.Pow(2, powerOfTwo); digit++)
            {
                // add next rightmost digit to sum
                sum += (int)((Math.Pow(2, powerOfTwo) / Math.Pow(10, digit) % 10));
            }
            // write output to console, and save solution to clipboard
            Console.Write("Power of two: {0} Sum of digits: {1}'n", powerOfTwo, sum);
            Clipboard.SetText(sum.ToString());
            Console.WriteLine("Answer copied to clipboard. Press any key to exit.");
            Console.ReadKey();
        }
    }
}

它似乎非常适合 powerOfTwo <34。我的计算器用完了上面的有效数字,所以我无法测试更高的功率。但是跟踪程序,看起来没有发生溢出:计算的位数随着 powerOfTwo = 1000 的增加而逐渐增加,并且数字的总和(平均(也随着 powerOfTwo 的增加而增加。

对于我应该执行的实际计算,我得到输出:

二的幂:1000 数字总和:1189

但1189不是正确的答案。我的程序有什么问题?我愿意接受任何和所有建设性的批评。

数字 2^1000 的数字之和是多少

为了计算如此大的数字的值,你不仅需要成为一名优秀的程序员,还需要成为一名优秀的数学家。这里有一个提示给你,有熟悉的公式 a x= e xln a ,或者如果您愿意,AX = 10x log a

更具体地针对您的问题21000 求 2 的公共(基数为 10(对数,乘以 1000;这是 10 的幂。如果您得到类似 10 53.142 (53.142 = log 2 值 * 1000( - 您很可能会得到 - 那么那就是 1053 x 100.142;只需计算 100.142,您将获得一个介于 1 和 10 之间的数字;并将其乘以 10 53,但是这个 10 53 将没有用,因为53 零和将仅为零。

对于 C# 中的日志计算

Math.Log(num, base);

为了获得更高的准确性,您可以使用大整数的日志和Pow函数。

现在休息编程帮助我相信你可以从你身边得到。

普通int无法帮助您处理如此大的数字。甚至没有long.它们从来不是为处理如此巨大的数字而设计的。 int可以存储大约 10 位数字(精确最大值:2,147,483,647 (,long存储大约 19 位数字(精确最大值:9,223,372,036,854,775,807 位数字(。但是,内置Windows计算器的快速计算告诉我2^1000是一个超过300位的数字。

(旁注:确切的值可以分别从int.MAX_VALUElong.MAX_VALUE获得(

由于您想要精确的数字总和,即使是floatdouble类型也不起作用,因为它们只存储几到几十位数字的有效数字。(浮点数为 7 位,双精度为 15-16 位(。阅读此处了解有关浮点表示、双精度的更多信息

但是,C# 提供了内置的算术 BigInteger任意精度,这应该适合您的(测试(需求。即可以用任意位数进行算术(当然理论上。实际上,它实际上受到物理机器内存的限制,并且也需要时间,具体取决于您的CPU功率(


回到你的代码,我认为问题就在这里

Math.Pow(2, powerOfTwo)

这会溢出计算。嗯,不是真的,但正如我所说,double精度并不能精确地代表结果的实际值。

不使用 BigInteger 类的解决方案是将每个数字存储在它自己的 int 中,然后手动执行乘法。

static void Problem16()
{
    int[] digits = new int[350];
    //we're doing multiplication so start with a value of 1
    digits[0] = 1;
    //2^1000 so we'll be multiplying 1000 times
    for (int i = 0; i < 1000; i++)
    {
        //run down the entire array multiplying each digit by 2
        for (int j = digits.Length - 2; j >= 0; j--)
        {
            //multiply
            digits[j] *= 2;
            //carry
            digits[j + 1] += digits[j] / 10;
            //reduce
            digits[j] %= 10;
        }
    }
    //now just collect the result
    long result = 0;
    for (int i = 0; i < digits.Length; i++)
    {
        result += digits[i];
    }
    Console.WriteLine(result);
    Console.ReadKey();
}

我使用了向左按位移动。然后转换为数组并对其元素求和。我的最终结果是 1366,不要忘记添加对系统数字的引用;

BigInteger i = 1;
         i = i << 1000;
        char[] myBigInt = i.ToString().ToCharArray();
        long sum = long.Parse(myBigInt[0].ToString());
        for (int a = 0; a < myBigInt.Length - 1; a++)
        {
            sum += long.Parse(myBigInt[a + 1].ToString());
        }
        Console.WriteLine(sum);

因为这个问题是特定于 C# 的,使用 bigInt 可能会完成这项工作。 在Java和Python中,它也可以工作,但是在C和C ++等语言中,如果该工具不可用,则必须使用数组并进行乘法。 在数组中取一个大数字并将其乘以 2。 这很简单,将有助于提高您的逻辑技能。 并来到欧拉项目。 有一个你必须找到100的问题!您可能还希望为此应用相同的逻辑。

尝试使用 BigInteger type ,2^100 最终将得到一个非常大的数字,即使是双精度才能处理。

BigInteger bi= new BigInteger("2"); 
bi=bi.pow(1000); 
// System.out.println("Val:"+bi.toString()); 
String stringArr[]=bi.toString().split(""); 
int sum=0; 
for (String string : stringArr) 
{ if(!string.isEmpty()) sum+=Integer.parseInt(string); } 
System.out.println("Sum:"+sum);
------------------------------------------------------------------------
output :=> Sum:1366

这是我在 JavaScript 中的解决方案

(function (exponent) {
  const num = BigInt(Math.pow(2, exponent))
  let arr = num.toString().split('')
  arr.slice(arr.length - 1)
  const result = arr.reduce((r,c)=> parseInt(r)+parseInt(c))
  console.log(result)
})(1000)

这不是一个严肃的答案——只是一个观察。

虽然尝试仅使用一种编程语言击败欧拉计划是一个很好的挑战,但我相信该网站旨在促进所有尝试它的程序员的视野。换句话说,考虑使用不同的编程语言。

一个通用的Lisp解决方案可以像这样简单

(defun sum_digits (x)
    (if (= x 0)
        0
        (+ (mod x 10) (sum_digits (truncate (/ x 10))))))
(print (sum_digits (expt 2 1000)))
 main()
 {
   char c[60];
  int k=0;
     while(k<=59)
      {
    c[k]='0';
   k++;
    }
       c[59]='2';
       int n=1;
     while(n<=999)
       {
       k=0;
     while(k<=59)
      {
        c[k]=(c[k]*2)-48;
        k++;
      } 
    k=0;
     while(k<=59)
        {
        if(c[k]>57){ c[k-1]+=1;c[k]-=10;   }
       k++;
         }
       if(c[0]>57)
        {
         k=0;
         while(k<=59)
           {
         c[k]=c[k]/2;
          k++;
           }
           printf("%s",c);
             exit(0);
           }
            n++;
            }
          printf("%s",c);
              } 

Python 使得使用单行计算这一点变得非常简单:

print sum(int(digit) for digit in str(2**1000))

或者使用地图:

print sum(map(int,str(2**1000)))