Java:求和2 ^ 1000的所有数字

时间:2012-12-25 10:44:35

标签: java bigdecimal

我正在尝试解决Project Euler问题#16,我需要将所有数字加到2 ^ 1000。我已经遇到了这么大的问题。我的程序适用于10 ^ 16以下的任何数字,但之后失败了。这告诉我,我的逻辑是正确的。我继续将所有变量和方法转换为BigDecimal,但现在程序运行不正常。它按原样编译,没有错误;它只是没有终止。有没有人知道我在哪里出错?

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Powerdigitsum {

    private static final BigDecimal one = new BigDecimal("1");
    private static final BigDecimal ten = new BigDecimal("10");

    private static BigDecimal sumofDigits(BigDecimal n){

        BigDecimal sum = new BigDecimal("0");

        while(n.compareTo(one) == 1 || n.compareTo(one) == 0){

            sum.add(n.remainder(ten));

            n.divide(ten);

            n = n.setScale(0, RoundingMode.FLOOR);

        }

    return sum;

    }

    public static void main(String[] args) {

        final double the_number = Math.pow(2,1000);

        final double test = 15;

        final BigDecimal two_to_the_thousandth_power = new BigDecimal(test);

        System.out.println(sumofDigits(two_to_the_thousandth_power));

    }

}

8 个答案:

答案 0 :(得分:5)

正确使用BigInteger

BigInteger a = new BigInteger("2").pow(1000);

答案 1 :(得分:2)

整个方法有点不对劲。见:

private static BigInteger sumOfDigits(BigInteger n) {
    BigInteger sum = BigInteger.ZERO;
    while (n.compareTo(BigInteger.ZERO) == 1) {
        sum = sum.add(n.remainder(ten));
        n = n.divide(ten);
    }
    return sum;
}

你需要比较零,而不是一个。你需要为BigIntegers和BigDecimals赋值,它们的方法本身不做任何事情,这些类的实例是不可变的。

对于整数,使用BigInteger通常会更好。小数部分(从分裂到达)就被扔掉了。

答案 2 :(得分:1)

final double the_number = Math.pow(2,1000);

这不起作用,因为the_number不足以取得结果。您需要将pow电话转换为BigInteger

BigInteger result = new BigInteger("2").pow(1000);

但请注意..这可能需要一些时间..

答案 3 :(得分:1)

不要使用BigDecimal(double)构造函数:它受double基元类型的限制,它不能代表2 ^ 1000。

您可以使用BigInteger。沿着这些方向的东西应该起作用(可能不是最理想的,但......):

public static void main(final String... args)
{
    // 2^1000
    final BigInteger oneTo2000 = BigInteger.ONE.shiftLeft(1000);

    BigInteger digitSum = BigInteger.ZERO;

    // We don't want to split against the empty string, the first element would be ""
    for (final String digit: oneTo2000.toString().split("(?<=.)"))
        digitSum = digitSum.add(new BigInteger(digit));

    System.out.println(digitSum);
}

答案 4 :(得分:0)

import java.math.BigInteger;

public class Problem16 {
public static void main(String[] args) {

   BigInteger number2 = new BigInteger("2");   
   BigInteger number3 = new  BigInteger("0");
   number3 =number2.pow(1000);

   String str = number3.toString();
BigInteger sum = new BigInteger("0");

 for(int i=0; i<str.length(); i++)
  {
    char c= str.charAt(i); 

    int value = Character.getNumericValue(c);
    BigInteger value2 = new BigInteger(Integer.toString(value));
     sum =sum.add(value2) ; 
  }
System.out.println(sum);

}

}

答案 5 :(得分:0)

如果你认为BIGINTEGER正在玩耍和/或不想使用它/学习如何使用它,那么这个算法就是你的选择。

考虑如何手动计算2 ^ 1000。你从2 ^ 1开始并反复乘以2。现在注意,对于每3个幂的AT LEAST,2的幂的位数增加1(可以在4个幂之后,如1024到8192)。所以制作像这样的锯齿状2D阵列

int a[][]= new int[1000][];
for(int i=0;i<1000;i++)
{
    a[i]= new int[1+(i/3)];
}

然后将[0] [0]初始化为2.在此之后,您需要编写一个for循环,以便从最右边的位置填充每一行。因此,使两个变量“数字”和“携带”。数字是您将输入到您正在处理的行中的数字,并且进位是您将要进行下一次计算的数字,并添加到2的乘积以及您将其乘以的任何数字。小心更新数字的顺序并在每次计算后将其重新初始化并重新初始化为零。我认为最困难的部分是提出for循环的限制,以便它适合每3个权力的东西。你可以通过制作一个每行增加一个的三角形锯齿状数字来简化这个过程。我这样做了。这是我的整个代码。

import java.util.*;
public class ProjectEuler16 
{
    public static void main(String[] args) 
    {
        long t1=System.currentTimeMillis();
        ProjectEuler16 obj = new ProjectEuler16();
        System.out.println(obj.bigNumHandler());
        long t2= System.currentTimeMillis();
        System.out.println(t2-t1);
    }
    int bigNumHandler()
    {
        int a[][] = new int[1000][];
        for(int i=0;i<1000;i++)
        {
            a[i]= new int[1+(i/3)];
        }
        a[0][0]=2;
        for(int i=1;i<1000;i++)
        {   
            int carry=0;
            int digit=0;
            int f=0;
            if(i%3==0)
            {
                f=1;
            }
            for(int j=a[i-1].length-1+f;j>=0;j--)
            {
                if(j==0&f==1)
                {
                    a[i][0]=carry;
                }
                else
                {
                     digit=((2*a[i-1][j-f])+carry)%10;
                     carry=((2*a[i-1][j-f])+carry)/10;
                     a[i][j]=digit;
                }
            }

        }
        int sum=0;
        for(int k=0;k<a[999].length;k++)
        {
           sum=sum+a[999][k];
        }
        return sum;
   }
}

请注意,最后一行列出了2 ^ 1000的数字。我想你可以弄清楚如何对数字求和。该程序花了大约5秒钟才得出答案。

答案 6 :(得分:0)

溶液::::

import java.math.BigInteger;

public class PR9 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BigInteger zero=BigInteger.valueOf(0);
        BigInteger ten=BigInteger.valueOf(10);
        BigInteger sum=zero;
        BigInteger a = new BigInteger("2").pow(1000);

        while(a.compareTo(zero)>0){
            sum=sum.add(a.mod(ten));
            a=a.divide(ten);
        }
        System.out.println(sum);


       }
    }

输出:::::
1366

答案 7 :(得分:0)

import java.math.BigInteger;

public class P16 {

    public static BigInteger digitSum(int n) {
        BigInteger sum = BigInteger.ZERO;
        BigInteger number = new BigInteger("2").pow(n);

        while (number.compareTo(BigInteger.ZERO) == 1) {
            BigInteger remainder = number.remainder(BigInteger.TEN);
            sum = sum.add(remainder);
            number = number.divide(BigInteger.TEN);
        }

        return sum;
    }

    public static void main(String[] args) {
        final double START = System.nanoTime();
        System.out.println(digitSum(Integer.parseInt(args[0])));
        final double DURATION = System.nanoTime() - START;
        System.out.println("Duration: " + DURATION / 1000000 + "ms.");
    }
}

虽然可能有一种方法可以在不使用BigIntegers的情况下解决这个问题,但很明显它们使代码运行得更快。 我只花了大约4ms才找到答案。