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

时间:2013-10-11 04:11:59

标签: c# arbitrary-precision

这是来自problemProject Euler,此问题包含一些源代码,因此请考虑这是您的剧透警报,以防您有兴趣自行解决。不鼓励为问题分发解决方案,这不是我想要的。我真诚地需要在正确的方向上进行一点点推动和指导。

问题如下:

  

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&lt;我的计算器超出了那个数字,所以我无法测试更高的功率。但是跟踪程序,看起来没有发生溢出:计算的位数随着powerOfTwo = 1000的增加而逐渐增加,并且数字的总和也(平均)随着powerOfTwo的增加而增加。

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

  

2的幂:1000位数:1189

但1189不是正确的答案。我的计划有什么问题?我对所有建设性的批评持开放态度。

11 个答案:

答案 0 :(得分:13)

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

更具针对您的问题 2 1000 找到2的公共(基数10)对数,并乘以1000;这是10的幂。如果你得到像10 53.142 (53.142 = log 2值* 1000) - 你最有可能 - 那么这就是10 53 x 10 0.142 ;只评估10 0.142 ,您将获得1到10之间的数字;并乘以10 53 ,但这10 53 将没有用,因为53零和将仅为零。

用于C#

中的日志计算
Math.Log(num, base);

为了更准确,您可以使用Big Integer的Log和Pow功能。

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

答案 1 :(得分:9)

普通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位)。 Read here for more information about floating point representation, double precision

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


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

Math.Pow(2, powerOfTwo)

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

答案 2 :(得分:2)

不使用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();
}

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

因为问题是c#具体使用bigInt可能会完成这项工作。在java和python中它也可以工作但是在c和c ++这样的语言中,设备不可用你必须采用数组并进行乘法运算。取数组中的大数字并将其乘以2.这很简单,有助于提高你的逻辑技能。来到欧拉项目。有一个问题,你必须找到100!您可能也想为此应用相同的逻辑。

答案 5 :(得分:0)

尝试使用BigInteger type,2 ^ 100将结束一个非常大的数字,即使是双倍处理。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

这是我在 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)

答案 8 :(得分:-1)

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

尽管尝试使用一种编程语言击败Project Euler是一个很好的挑战,但我相信该网站旨在进一步扩大所有尝试它的程序员的视野。换句话说,请考虑使用不同的编程语言。

问题的Common Lisp solution可以像

一样简单
(defun sum_digits (x)
    (if (= x 0)
        0
        (+ (mod x 10) (sum_digits (truncate (/ x 10))))))

(print (sum_digits (expt 2 1000)))

答案 9 :(得分:-1)

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

答案 10 :(得分:-1)

Python使用oneliner计算它非常简单:

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

或者使用map:

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