I have a method that is converting a decimal (double value) into a fraction and putting the numerator and denominator values into an int[] of size 2.
Testing it works out fine for most values except when I hit 0.0001. Then the return value is 1.0/1.0.
The method:
private static int[] toFractionPos(double x){
String[] parts = Double.toString(x).split("\\.");
double den = Math.pow(10, parts[1].length()); //denominator
double num = Double.parseDouble(parts[0]) * den + Double.parseDouble(parts[1]); //numerator
return reduceFraction((int)num, (int)den);
}
reduceFraction() method:
public static int[] reduceFraction(int num, int den){
int gcf = GCF(num, den); //greatest common factor
int[] rf = {num/gcf, den/gcf};
return rf;
}
Thanks!
The algorithm seems fine. However, using double is not suitable for this kind of problem, because precision decreases as the scale grows.
You should use BigDecimal and BigInteger instead. I've roughly modified your example so that it works with them, but I haven't taken care of details, i.e. parsing the String shouldn't be necessary since scale can be retrieved from a BigDecimal with a getter, you can configure different rounding modes, etc:
import java.math.BigDecimal;
import java.math.BigInteger;
public class Sample {
static int[] toFractionPos(BigDecimal x) {
String[] parts = x.toString().split("\\.");
BigDecimal den = BigDecimal.TEN.pow(parts[1].length()); // denominator
BigDecimal num = (new BigDecimal(parts[0]).multiply(den)).add(new BigDecimal(parts[1])); // numerator
return reduceFraction(num.intValue(), den.intValue());
}
static int[] reduceFraction(int num, int den) {
int gcd = BigInteger.valueOf(num).gcd(BigInteger.valueOf(den)).intValue(); // greatest
// common
// divisor
int[] rf = { num / gcd, den / gcd };
return rf;
}
public static void main(String[] args) {
int[] fraction = toFractionPos(new BigDecimal("0.0001"));
System.out.println(fraction[0] + "/" + fraction[1]); // 1/10000
}
}
Note: optimizations left as an excercise ;)
You shouldn't work with doubles as you are losing precision and this can lead to serious errors. But in the case of 1.0001 the problem is that:
Double.toString(1.0001) == "1.0E-4"
Then you try to parse "0E-4" and you get 0 instead of 1. You could do the following if you expect at most 10 decimal points:
DecimalFormat df = new DecimalFormat("0",
DecimalFormatSymbols.getInstance(Locale.ENGLISH));
df.setMaximumFractionDigits(10);
String[] parts = df.format(x).split("\\.");
How about this?
private static int[] toFractionPos(double x){
int den = (int)Math.pow(10,(int)Math.log10(Integer.MAX_VALUE));
int num = (int)(x*den);
return reduceFraction(num, den);//this came from your code
}
I think this will work,
public int[] Fraction(double n) {
BigDecimal p = BigDecimal.ONE;
BigDecimal dn = BigDecimal.valueOf(n);
while(true){
dn = dn.multiply(p);
if( dn.compareTo(new BigDecimal(dn.toBigInteger()))==0 )
break;
else
p = p.multiply(BigDecimal.TEN);
}
BigInteger num=dn.toBigInteger(), den=p.toBigInteger(), g=num.gcd(den);
num = num.divide(g);
den = den.divide(g);
int[] res = new int[2];
res[0] = num.intValue();
res[0] = den.intValue();
return res;
}
Related
i'm trying to convert decimals into fractions. my program works just fine for other numbers. however when trying to find the numerator and denominator for 1.0923059908040425e-33,
java gives 1/9
where as python gives 0.
this is my code for java:
class Rational {
public static void main(String[] args) {
println(getDenominator(convertDecimalToFraction(1.0923059908040425e-33)));
}
public static int getNumerator(String fraction) {
return Integer.valueOf(fraction.substring(0, fraction.indexOf(".")));
}
public static int getDenominator(String fraction) {
fraction = fraction.substring(fraction.indexOf("/") + 1);
return Integer.valueOf(fraction.substring(0, fraction.indexOf(".")));
}
static private String convertDecimalToFraction(double x){
if (x < 0){
return "-" + convertDecimalToFraction(-x);
}
double tolerance = 1.0E-6;
double h1=1; double h2=0;
double k1=0; double k2=1;
double b = x;
do {
double a = Math.floor(b);
double aux = h1; h1 = a*h1+h2; h2 = aux;
aux = k1; k1 = a*k1+k2; k2 = aux;
b = 1/(b-a);
} while (Math.abs(x-h1/k1) > x*tolerance);
return h1+"/"+k1;
}
}
and this is python:
print(fractions.Fraction(1.0923059908040425e-33).limit_denominator())
i think there's problem in my java code because i'm expecting 0 as correct output, but there is built-in library available for Fractions, and i don't want to use any third-party libraries.
java code works on mostly all inputs. only problem with this one input. please point me error if any.
i would really appreciate if you can provide me with a method or logic that can solve this problem
print(fractions.Fraction(1.0923059908040425e-33)) gives 6385627976105849/5846006549323611672814739330865132078623730171904
after adding limit_denominator, it becomes 0.
i don't know what is going on here..
Well a bit a debugging would immediately show what happens. convertDecimalToFraction returns "1.0/9.15494383825455E32" which is not stupid, but getDenominator just ignores the E32. You should mimic the limit_denominator from Python and say that if x<tolerance then the returned value shall be "0./1.":
static private String convertDecimalToFraction(double x){
if (x < 0){
return "-" + convertDecimalToFraction(-x);
}
double tolerance = 1.0E-6;
if (x < tolerance) {
return "0./1.";
}
double h1=1; double h2=0;
double k1=0; double k2=1;
double b = x;
do {
double a = Math.floor(b);
double aux = h1; h1 = a*h1+h2; h2 = aux;
aux = k1; k1 = a*k1+k2; k2 = aux;
b = 1/(b-a);
} while (Math.abs(x-h1/k1) > x*tolerance);
return h1+"/"+k1;
}
Here is my code:
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
import java.security.SecureRandom;
public class Solution {
static BigDecimal result;
static Double y = 0.0;
static int o;
static int[] factors = new int[1];
static int current = 0;
public static void main(String[] args) {
Scanner a1 = new Scanner(System.in);
int b = a1.nextInt();
o = b;
result = new BigDecimal(Integer.valueOf(b));
BigInteger N = new BigInteger(Integer.toString(b - 1));
factor(N);
boolean isPrimitive = true;
for (int i1 = 2; i1 < 10000;i1++) {
isPrimitive = true;
//System.out.println("Enter the value of a large prime no");
BigInteger value = new BigInteger(String.valueOf(o-1));
//System.out.println("\nEnter the value of alpha");
BigInteger checking = new BigInteger(String.valueOf(i1));
BigInteger bigValue = new BigInteger(String.valueOf(o));
for(int i=0;i<factors.length;i++)
{
BigInteger temp = checking.pow(factors[i]);
// System.out.println("checking "+i1+": "+temp+" mod "+o+" = " + (temp.mod(new BigInteger(String.valueOf(o)))));
if ((temp.mod(bigValue)).equals(BigInteger.ONE)) {
isPrimitive = false;
break;
}
}
if(isPrimitive) {
System.out.print(i1+" ");
break;
}
else{
//System.out.println("not primitive roots");
}
}
System.out.println(result.toBigInteger());
}
private final static BigInteger ZERO = new BigInteger("0");
private final static BigInteger ONE = new BigInteger("1");
private final static BigInteger TWO = new BigInteger("2");
private final static SecureRandom random = new SecureRandom();
public static BigInteger rho(BigInteger N) {
BigInteger divisor;
BigInteger c = new BigInteger(N.bitLength(), random);
BigInteger x = new BigInteger(N.bitLength(), random);
BigInteger xx = x;
// check divisibility by 2
if (N.mod(TWO).compareTo(ZERO) == 0) return TWO;
do {
x = x.multiply(x).mod(N).add(c).mod(N);
xx = xx.multiply(xx).mod(N).add(c).mod(N);
xx = xx.multiply(xx).mod(N).add(c).mod(N);
divisor = x.subtract(xx).gcd(N);
} while ((divisor.compareTo(ONE)) == 0);
return divisor;
}
public static void factor(BigInteger N) {
//System.out.println("result = "+result);
if (N.compareTo(ONE) == 0) return;
if (N.isProbablePrime(20)) {
// System.out.println("n = "+N);
if ((N.doubleValue() != (y)) &&N.doubleValue() != (1.0) ) {
// System.out.println("j = "+String.valueOf(1.0 - (1.0/(N.doubleValue()))));
BigDecimal j = new BigDecimal(String.valueOf(1.0 - (1.0/(N.doubleValue()))));
//System.out.println("result = " +result+" * "+j);
result = new BigDecimal(String.valueOf(result.doubleValue() * j.doubleValue()));
//System.out.println(result.multiply(j));
//System.out.println((String.valueOf(1.0 - (1.0/(N.doubleValue())))));
y = N.doubleValue();
if (current == factors.length) {
int[] temp = new int[factors.length+1];
for (int i = 0; i < factors.length;i++) {
temp[i] = factors[i];
}
factors = temp;
}
factors[current] = o/y.intValue();
// System.out.println(o+"/"+y.intValue());
current++;
//System.out.println("result = "+result);
}
return;
}
BigInteger divisor = rho(N);
factor(divisor);
factor(N.divide(divisor));
}
}
I am trying to find the first primitive root of a prime number, then the amount of primitive roots it has. Finding the amount is no problem for any number, but finding the first number is supposed to work for any number up to 1 billion on a certain system for on which other people have been successful. It works for all values up to around a million, but it doesn't work for 999994267. I don't know how I can possibly optimize this further. I have spent maybe 18 hours on this. I honestly can't figure this out. Any suggestions?
Math Explanation:
It takes the factors of the given number o, and tests every number from 2 if it's o/factor[1,2,...] is = 1, if none of o's factors are, it breaks and prints the number.
PS. It is possible, as many other people have done it on the same system.
Ok so thanks to #IgorNikolaev above in the comments of my question I have figured out my problem and solved it. To fully optimize a modPow operation you need to use modular arithmetic.
Here are some links he provided which greatly helped:
en.wikipedia.org/wiki/Modular_arithmetic
en.wikipedia.org/wiki/Modular_exponentiation
And here is the code I wrote based on those links:
private static BigInteger fastModPow(BigInteger base, BigInteger exponent, final BigInteger modulo) {
BigInteger result = BigInteger.ONE;
while (exponent.compareTo(BigInteger.ZERO) > 0) {
if (exponent.testBit(0))
result = (result.multiply(base)).mod(modulo);
exponent = exponent.shiftRight(1);
base = (base.multiply(base)).mod(modulo);
}
return result.mod(modulo);
}
As you will see in the first link, it sort-of "wraps around" to find the mod of a power.
Thanks for everyones help.
Is there a proper way for converting a double value to a BigInteger value and later back? In the best case without loosing data. The problem is, that I don't know how many decimal places the double values have. But I need this conversion for an Algorithm which only works with non decimal values. After the Algorithm finishes I have to convert it back.
An easy example what I need: for example the sum of 2 double values but the "sum" function works only with BigInteger.
You can do it in 5 steps:
double d1 = 0.1; //your original double
BigDecimal bd1 = new BigDecimal(d1); //convert to BigDecimal
BigInteger bi = bd1.unscaledValue(); //convert to BigInteger
//here do your stuff with the BigInteger
BigDecimal bd2 = new BigDecimal(bi, bd1.scale()); //back to BigDecimal, applying scale
double d2 = bd2.doubleValue(); //convert to double
Full example applied to a sum method
Output:
0.1 + 0.1 = 0.2
0.1 + 10.1 = 10.2
0.1245 + 17.0 = 17.1245
Code:
public static void main(String[] args) {
test(0.1, 0.1);
test(0.1, 10.1);
test(0.1245, 17);
}
private static void test(double d1, double d2) {
System.out.println(d1 + " + " + d2 + " = " + sum(d1, d2));
}
private static double sum(double d1, double d2) {
BigDecimal bd1 = new BigDecimal(d1);
BigDecimal bd2 = new BigDecimal(d2);
int shift = Integer.max(bd1.scale(), bd2.scale());
BigInteger bi1 = bd1.scaleByPowerOfTen(shift).toBigInteger();
BigInteger bi2 = bd2.scaleByPowerOfTen(shift).toBigInteger();
BigInteger sum = sum(bi1, bi2);
return new BigDecimal(sum, shift).doubleValue();
}
private static BigInteger sum(BigInteger i1, BigInteger i2) {
return i1.add(i2);
}
This program is based on the BigDecimal-and-scale idea, as in assylias's answer, but modified to unconditionally use the maximum possible required scale. This allows the same scale to be used across a stream of numbers, without seeing all the numbers before processing any of them. The cost is that it will usually return unnecessarily large BigInteger values.
The scale factor, "1e1074", is based on the observation that all finite double numbers are integer multiples of Double.MIN_VALUE, which has 1074 decimal digits after the decimal point. No double can have more decimal digits after the decimal point.
import java.math.BigDecimal;
import java.math.BigInteger;
public class Test {
public static void main(String[] args) {
testit(Double.MIN_VALUE);
testit(Double.MAX_VALUE);
testit(0);
testit(1.0);
testit(Math.E);
testit(Math.PI);
}
private static void testit(double d) {
double roundTrip = scaledIntegerToDouble(doubleToScaledInteger(d));
if (d != roundTrip) {
System.out.println("ERROR: " + d + " " + roundTrip);
}
}
public static final BigDecimal scale = new BigDecimal("1e1074");
public static BigInteger doubleToScaledInteger(double d) {
BigDecimal bd = new BigDecimal(d).multiply(scale);
return bd.toBigIntegerExact();
}
public static double scaledIntegerToDouble(BigInteger bi) {
BigDecimal bd = new BigDecimal(bi).divide(scale);
return bd.doubleValue();
}
}
package test;
import java.math.*;
public class HelloWorld{
public static BigInteger sumBigInteger(BigInteger n1,BigInteger n2){
return n1.add(n2);
}
public static double sumDouble(double n1,double n2){
int scale=1;
int max = Math.max(((""+n1).split("\\."))[1].length(), ((""+n2).split("\\."))[1].length());
for (int i=0;i<max;i++) scale*=10;
BigInteger nbr1 = new BigDecimal(n1*scale).toBigInteger();
BigInteger nbr2 = new BigDecimal(n2*scale).toBigInteger();
return (sumBigInteger(nbr1,nbr2).doubleValue() / scale);
}
public static void main(String []args){
double n1=117.22 , n2=56.945;
System.out.println(n1+" + "+n2+" = "+sumDouble(n1,n2));
}
}
Output:
117.22 + 56.945 = 174.165
Here is my problem, I need to create a program that runs the following instructions.
Create java class named Fraction. This class is used to represent a
ratio of two integers. Include mutator methods that allow the user to
set the numerator and the denominator. Also include a method to
display the fraction on the screen as a ration (e.g. 5/9). This method
does not need to reduce the fraction to lowest terms.
The fraction class should contain the following:
Private instance variables to store the numerator, denominator, and the ratio_value.
Constructor(s) that set all of the instance variables.
Public methods to get and set the instance variables.
A public method named reduce( ) that returns lowest terms of a fraction.
A public method named toString( ) that returns a String containing the fraction as a ratio.
A private method name gcd() that return the greatest common divisor of two integers.
Create a test program that allows the user to create array of 7
fractions. Then the program will sort the fraction in ascending order.
The highest and the lowest fractions are thrown away and the remaining
fractions are added together. The program should display all the
fractions and their sum. The sum should be reduced to lowest terms and
displayed on the screen. For example, if the sum is 20/60, the program
should display 1/3.
Write a sort method in the test program to sort the array of fractions
and calculate the sum.
Assume you have the following 7 fractions: 6/7, 2/4, 3/4, 3/18, 1/8,
10/20, 2/6, then an example of the output after throwing away the
lowest and the largest fractions, will be:
3 / 18 + 2 / 6 + 2 / 4 + 10 / 20 + 3 / 4 = 9 / 4
I completely lost on how to solve this and stuck where I am at. Below is a copy of my class and .main file. I have some different things that I have tried commented out with '//' so sorry for the long codes.
package homework_5;
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
public class Arrays_hw5 {
private static final Scanner keyb = null;
public static void main(String[] args) {
Fraction [] fr = new Fraction[7];
// Fraction fr1 = new Fraction();
// Fraction fr2 = new Fraction();
// Fraction fr3 = new Fraction();
// Fraction fr4 = new Fraction();
// Fraction fr5 = new Fraction();
// Fraction fr6 = new Fraction();
// Fraction fr7 = new Fraction();
String reduce = "";
int numerator = 0, denominator = 0;
Scanner keyb = null;
FileInputStream fis = null;
// Scanner keyb = new Scanner(System.in);
try {
fis = new FileInputStream(new File("fractions"));
keyb = new Scanner(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// keyb.useDelimiter("/");
// keyb.useDelimiter(" ");
// fr1.setNumerator(keyb.nextInt());
// fr1.setDenominator(keyb.nextInt());
// System.out.println(fr1);
// fr2.setNumerator(keyb.nextInt());
// fr2.setDenominator(keyb.nextInt());
// System.out.println(fr2);
// fr3.setNumerator(keyb.nextInt());
// fr3.setDenominator(keyb.nextInt());
// System.out.println(fr3);
// fr4.setNumerator(keyb.nextInt());
// fr4.setDenominator(keyb.nextInt());
// System.out.println(fr4);
// fr5.setNumerator(keyb.nextInt());
// fr5.setDenominator(keyb.nextInt());
// System.out.println(fr5);
// fr6.setNumerator(keyb.nextInt());
// fr6.setDenominator(keyb.nextInt());
// System.out.println(fr6);
// fr7.setNumerator(keyb.nextInt());
// fr7.setDenominator(keyb.nextInt());
// System.out.println(fr7);
for (int i = 0; i < fr.length; i++)
{
//System.out.println("Enter numerator then denominator, hit enter after each entry: ");
fr[i] = new Fraction(i, i);
fr[i].setNumerator(keyb.nextInt());
fr[i].setDenominator(keyb.nextInt());
System.out.print(fr[i] + " ");
//System.out.print(fr[i].decimal(numerator, denominator));
}
// Arrays.sort(fr);
// for (int i = 0; i < fr.length; i++)
// System.out.println(fr[i].decimal(numerator, denominator));
// Fraction [] frac = {fr[1], fr[2], fr[3], fr[4], fr[5], fr[6], fr[7]};
// Arrays.sort(frac);
// for (int i = 0; i < 7; i++)
// System.out.println(frac[i]);
}
public static void selectionSort(int[]arr) //sorting array
{
int smallest = 0;
for (int outer = 0; outer < arr.length - 1; outer++)
{
smallest = outer;
for(int inner = outer + 1; inner < arr.length; inner++)
{
if (arr[inner] < arr[smallest])
smallest = inner;
}
int v = arr[outer];
arr[outer] = arr[smallest];
arr[smallest] = v;
}
}
}
here is my Fraction class
package homework_5;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Fraction {
public int numerator = 1;
public int denominator = 1;
public int gcd;
public Fraction() {
super();
}
public Fraction(int n, int d) {
numerator = n;
denominator = d;
}
public int getNumerator() {
return numerator;
}
public void setNumerator(int numerator) {
this.numerator = numerator;
}
public int getDenominator() {
return denominator;
}
public void setDenominator(int denominator) {
this.denominator = denominator;
}
private static int gcd(int numerator, int denominator) {
return denominator == 0 ? numerator : gcd(denominator, numerator % denominator);
}
public double decimal(double numerator, double denominator) {
return numerator / denominator;
}
public static String reduce(int numerator, int denominator) {
int gcd = gcd(numerator, denominator);
return (numerator / gcd) + "/" + (denominator / gcd);
}
#Override
public String toString() {
return numerator + "/" + denominator;
}
}
So far all I am able to do is print out the 7 fractions from a .txt file formatted like:6 7 2 4 3 4 3 18 1 8 10 20 2 6
but I want to have a text file formatted like:6/7 2/4 3/4 3/18 1/8 10/20 2/6
I can not figure out how to get a deliminator to read the '/' and the ' '.
Thank you for any help.
From the java docs you can just method chain the delimiter you want onto the constructor for Scanner as a regular expression.
You want whitespace or a / symbol, so something like this should work. Untested, you may have to change the regex. If you do, just use a regex calculator online to fix it properly.
Scanner keyb = new Scanner(new FileInputStream(new File("fractions")).useDelimiter("[/ | \s*]");
Thanks for the tip Ron, I got the program to read the '/' and ' ' by using this code: Now I just need to figure out how to sort, add and do the rest of the steps.
Scanner keyb = null;
FileInputStream fis = null;
// Scanner keyb = new Scanner(System.in);
try {
fis = new FileInputStream(new File("fractions"));
keyb = new Scanner(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
keyb.useDelimiter("[/ | *]");
I'm trying to solve Project Euler problem #16, where I need to sum all the digits of 2^1000. I've gotten stuck dealing with such a big number. My program worked for any number below 10^16, but failed afterwards. This told me that my logic was correct. I went ahead and converted all variables and methods to BigDecimal, but now the program does not run properly. It compiles as it is and there is no error; it just does not terminate. Does anyone have an idea on where I went wrong here?
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));
}
}
Just use BigInteger properly:
BigInteger a = new BigInteger("2").pow(1000);
The whole method is kinda wrong. See this:
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;
}
You needed to compare to zero, not one. And you need to assign the values for BigIntegers and BigDecimals, their methods do nothing on their own, the instances of those classes are immutable.
For integers, it's generally better to use BigInteger. The decimal part (that gets there from dividing) is just thrown away.
final double the_number = Math.pow(2,1000);
This won't work because the_number is not large enought to take the result. You need to convert the pow call to BigInteger:
BigInteger result = new BigInteger("2").pow(1000);
But be aware.. this can take some time..
Don't use the BigDecimal(double) constructor: it is limited by the double primitive type, which cannot represent 2^1000.
You can use a BigInteger. Something along these lines should work (probably suboptimal, but...):
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);
}
public class SumofDigitsPow {
public static void main(String[] args) {
//2(2^1000)
String temp = BigInteger.ONE.shiftLeft(1000).toString();
int sum = 0;
for(int i=0;i<temp.length();i++){
sum+= temp.charAt(i) - '0';
}
System.out.println(Integer.toString(sum));
}
}
java.math.BigInteger.shiftLeft(int n) method returns a BigInteger whose value is (this << n),So you can get the answer by using BigInteger and LeftShift Method
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);
}
}
IF YOU THINK BIGINTEGER IS CHEATING AND/OR don't feel like using it/learning how to use it, this algorithm is the way to go.
Think about how you would calculate 2^1000 by hand. You'd start with 2^1 and multiply by two repeatedly. Now notice that the number of digits of powers of two increase by 1 for AT LEAST every 3 powers (could be after 4 powers like with 1024 to 8192). So make a jagged 2D array like this
int a[][]= new int[1000][];
for(int i=0;i<1000;i++)
{
a[i]= new int[1+(i/3)];
}
Then initialize a[0][0] to 2. After this, you want to write a for loop such that each row is filled from the rightmost spot. So make two variables "digit" and "carry". Digit is the number that you will input into the row you're working on, and the carry is the one you're going to take to the next calculation and add to the product of 2 and whatever digit you're multiplying it with. Be careful with the order you update digit and carry and reinitialize them to zero after every calculation. I think the hardest part is coming up with the limits for the for loop, so that it fits with the every 3 powers thing. You can make this simpler by just making a triangular jagged array that increments by one every row. I did it like this though. Here's my whole code.
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;
}
}
Note that the last row lists the digits for 2^1000.I think you can figure out how to sum the digits. The program took about 5 seconds to come up with the answer.
solution::::
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);
}
}
output:::::
1366
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.");
}
}
While there maybe a way of solving this problem without the use of BigIntegers, it is clear that they make the code run way faster.
Mine only took about 4ms to find an answer.