Project Euler problem 2: sum of even Fibonacci numbers - java

I am trying to solve Project Euler problem 2 in Java:
public class Euler2 {
public static long GenerateFibonacci(int term) {
long sum = 0;
long fib = 0;
long f1 = 0;
long f2 = 1;
if (term <=1) return term;
for (int i = 1; i <= term; i++) {
fib = f1 + f2;
f1 = f2;
f2 = fib;
if(fib %2 ==0)
sum += fib;
}
return sum;
}
/**
* #param args
*/
public static void main(String[] args) {
int n = 100;
long result = GenerateFibonacci(n);
System.out.println("The sum of the even Fibonacci numbers is: "+result);
}
}
When n is small I get the right answer but for bigger values I get the wrong result. What's the problem here?

int is limited to 32-bit accuracy, long to 64-bit.
When you exceed the limit by adding numbers whose result is larger then the bit limit, they "roll over" and you lose the most significant bits from the result of the addition - essentially, they are "rounded" to 32/64 bits.
Here's an example of rolling over:
int i = Integer.MAX_VALUE; // 2147483647
i++; // -2147483648
Roughly speaking, each fibonnacci number is double the previous one, so roughly speaking you can only handle in the order of 64 iterations using a long as the total.

The largest long value in Java is 9223372036854775807. Adding 1 to this value produces -9223372036854775807 because the integer values in most programming languages come from a finite set of values, and when you reach the highest value and add one the sequence "wraps around" to the beginning.
If you need to go outside this range, which you will to get the 100th Fibonacci number, use BigInteger.

The sum is greater than Long.MAX_VALUE. You're correct (in your comment to #Bohemian) that n is less than that limit, but it is rather surprising how quickly this simple series can grow. The 100th Fibonacci number, for example, is 354224848179261915075. The sum of the first 100 is a 20 digit number, just to give you a feeling for the scale you're dealing with.

You need to use BigInteger, you can also use the fact that every third Fibonacci number is even.
public static BigInteger sumOfEvenFibonacci(int term) {
BigInteger sum = BigInteger.ZERO;
BigInteger f1 = BigInteger.ONE;
BigInteger f2 = BigInteger.ONE;
for (int i = 1; i <= term; i+=3) {
BigInteger fib = f1.add(f2);
sum = sum.add(fib);
f1 = f2.add(fib);
f2 = fib.add(f1);
}
return sum;
}
System.out.println(sumOfEvenFibonacci(100));
prints
1213946614199987541226

You can improve efficiency of 'GenerateFibonacci' with following code. This should be a comment but I can not format the code in comment, I am doing this in answer,
public class FibUtil {
//Constants used in equation to calculate nth fib term
private static final double fibA=1/Math.sqrt(5);
private static final double fibB=(1+Math.sqrt(5))/2;
private static final double fibC=(1-Math.sqrt(5))/2;
public static double getNthFibTerm(long n){
return fibA*(Math.pow(fibB, n)-Math.pow(fibC, n));
}
}
Further, based on euler 2 problem statement, you can just add only nth terms which are multiples of 3. I leave 'why' to you.

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package evenfibonaccisum;
import java.math.BigInteger;
/**
*
* #author blades of Aragon
*/
public class EvenFibonacciSum {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
long a=0;
long b=1;
long fib=1;
int i=10;
long sum=0;
while(fib<=4000000){
fib=a+b;
a=b;
b=fib;
if(fib>=4000000){
break ;
}
else{
if(fib%2==0){
sum=sum+fib;
}
}
}
System.out.println("sum of even Fibonacci "+sum);
}
}

Related

Java Euler number result infinity

I try to use a recursive function to calculate the Euler number in Java. It's OK when I enter small numbers into this formula:
But when I try to enter a bigger number like 1000 I get infinity.
Why it's happening. How I can fix it.
import java.util.Scanner;
public class enumber {
public static long fact(int a) {
if(a <= 1) {
return 1;
}
return a * fact(a - 1);
}
public static double calculate(int i) {
double cresult = Math.pow(fact(i), -1);
if(i == 0 ) {
return 1;
}
return cresult+calculate(i-1);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter i value: ");
int i = sc.nextInt();
double eresult = calculate(i);
System.out.println(eresult);
}
}
output;
Enter i value:
1000
Infinity
That's because you try to calculate the factorial of 1000....which is pretty huge.
Factorial 1000
You try to store it in a long value, but long's
max value is way smaller than 1000!. It basically doesn't fit anymore.
Consider using the class BigInteger (or BigDecimal), its in the default java sdk and you can directly output via println().
However you know the result already, its e, so you might only need to implement the Big-Class for the factorial.
You are exceeding the capacity of a long. But I would suggest you decide how much precision you want for e.
Let's say you want it to have an error of less than .0000001. Continue the iteration for e until the positive delta between your latest computation and the previous is less than or equal to your error.
If you want to take it to extremes, you can always use BigDecimal to increase the accuracy of your results.
I solved that problem by using loops. And for the old algorithm, I changed the fact method type to double. I get rid of Infinity. After that, I face "StackOverflowError".
What is a StackOverflowError?
My new algorithm is;
import java.util.Scanner;
public class enumber2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
double fact;
double eNumber = 0;
int i = in.nextInt();
while(i>0) {
fact=1;
for(int j=1; j<=i; j++) {
fact = fact * j;
}
eNumber = eNumber +(1.0/fact);
i--;
}
eNumber = eNumber +1;
System.out.println(eNumber);
}
}
even I enter big numbers after a little bit of patient I'm getting results without exception.

Fibonacci Sequence in Java taking too long?

I'm trying to find the sum of the Fibonacci sequence in Java, but the run time is taking way too long (or is it suppose to?). This slows down anytime I use an integer past 40.
Note: At 50, a negative value is returned which boggles my mind.
Any advice?
public static void main(String[] args) {
//Find Fibonacci sequence
int sum=getSum(50);
System.out.println("Sum of Fibonacci Numbers is " + sum);
}
static int getSum(int n){
if (n==0) return 0;
if (n==1 || n==2) return 1;
else return getSum(n-1) + getSum(n-2);
}
For n > 2, an invocation of your getSum(n) recursively invokes itself twice. Each of those invocations may recurse further. The total number of method invocations scales as 2^n, and 2^50 is a very large number. This poor scaling reflects the fact that the simple-minded recursive approach ends up needlessly recomputing the same results (e.g. fib(4)) a great many times, and it is why your program slows down so rapidly as you increase n.
The negative return value you get after a certain point arises from exceeding the limits of data type int. You could get a larger limit with a wider data type, presumably long. If that's not enough then you would need to go to something like BigInteger, at a substantial performance penalty.
You need to use long instead of int if you want to calculate the 50th Fibonacci number. The 50th Fibonacci number is 12586269025 and exceeds the maximum value of int (see http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibtable.html).
A non-recursive algorithm is likely going to be faster, see http://planet.jboss.org/post/fibonacci_sequence_with_and_without_recursion for the different implementations.
As the others already stated you should use long for the calculated fibonacci value, as the number will get very long very fast.
If your formost priority is performance you could use the following formula:
with
(Idea taken from Linear Algebra lecture, actual formula taken from Wikipedia.)
That way you will get the n-th fibonacci number in constant time (depending on the calculation of the n-th powers in the formula).
The following code calculates the fibonacci sequenc of the first 93 numbers with no waiting time (on my machine):
private static final double SQRT_FIVE = Math.sqrt(5);
private static final double GOLDEN_RATIO = (1 + SQRT_FIVE) / 2;
public static void main(String[] args) {
for(int i = 0; i <= 92; i++) {
System.out.println("fib(" + i + ") = " + calculateFibonacci(i));
}
}
public static long calculateFibonacci(int n) {
double numerator = Math.pow(GOLDEN_RATIO, n) - Math.pow(1-GOLDEN_RATIO, n);
double denominator = SQRT_FIVE;
// This cast should in general work, as the result is always an integer.
// Floating point errors may occur!
return (long)(numerator/denominator);
}
From the 94-th number on the long is no longer sufficent and you need to use BigInteger and fitting math operations, as the double calculations may produce calculation errors with such big numbers.
first, use a long instead of an int, to avoid overflow.
Secondly, use a non-recursive algorithm, as a recursive one exists in exponential time I think. A well designed non-recursive one will solve in linear time (I think).
Example non-recursive
static long getSum(int n){
long[] fibonacci = new long[n];
fibonacci[0] = 1;
fibonacci[1] = 1;
if (n==0) return 0;
if (n==1 || n==2) return 1;
for(int i = 2; i < n;i++){
fibonacci[i] = fibonacci[i-1]+ finonacci[i-2];
}
return fibonacci[n-1];
}
I haven't tested this, but it should work.
If you plan to call this method frequently, it might be prudent to store the array outside of the method, so that it is a simple lookup when doing this. This would provide a constant time solution for numbers that have already been calculated at least once. an example of that is below.
static long[] fibonacci= {1,1};
static long getSum(int n){
if (n==0) return 0;
if (n==1 || n==2) return 1;
int old_length = fibonacci.length;
if(fibonacci.length < (n-1)){
fibonacci = Arrays.copyOf(fibonacci,n);
}else{
return fibonacci[n-1];
}
for(int i = old_length; i < n;i++){
fibonacci[i] = fibonacci[i-1]+ finonacci[i-2];
}
return fibonacci[n-1];
}
Again, the example is untested, so a bit of debugging might be required.
Here is a linear time implementation of the algorithm that uses a constant overhead, instead of linear overhead.
static long getSum(int n){
long currentNum = 0;
long previousNum = 1;
long previousNum2 = 1;
if (n==0) return 0;
if (n==1 || n==2) return 1;
for(int i = 2; i < n;i++){
currentNum = previousNum+ previousNum2;
previousNum2 = previousNum;
previousNum = currentNum;
}
return currentNum;
}
Recursive solutions don't necessarily have to be slow. If you were to use this tail-recursive solution, you'd save up a lot of memory and still achieve great speed (e.g. Fib(10000) runs in 1.1s on my machine).
Here n is the sequence number for which you're calculating Fibonacci number, while f0 and f1 are two accumulators, for previous and current Fibonacci numbers respectively.
public class FibonacciRec {
public static int fib(int n, int f0, int f1) {
if (n == 0) {
return f0;
} else if (n == 1){
return f1;
} else {
return fib(n-1, f1, f0+f1);
}
}
public static void main(String[] args) {
System.out.println(fib(10, 0, 1));
}
}
If you want to keep the recursive approach as is, cache results of calculation in an array or map. When you have calculated one Fibonacci for n, save that result. Then, in your method first see if you have the result and return that if you do. Otherwise, make the recursive call(s). Here's an example: recursion is still used and it is quite fast:
public static Map<Long,Long> cache = null;
public static void main(String[] args) {
cache = new HashMap<Long,Long>();
cache.put(0L,0L);
cache.put(1L,1L);
cache.put(2L,1L);
Long sum=getSum(50L);
System.out.println("Sum of Fibonacci Numbers is " + sum);
}
static Long getSum(Long n){
if (cache.containsKey(n)) { return cache.get(n); }
else {
Long fib = getSum(n-1) + getSum(n-2);
cache.put(n, fib);
return fib;
}
}

Checking whether a number is in Fibonacci Sequence?

It was asked to find a way to check whether a number is in the Fibonacci Sequence or not.
The constraints are
1≤T≤10^5
1≤N≤10^10
where the T is the number of test cases,
and N is the given number, the Fibonacci candidate to be tested.
I wrote it the following using the fact a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square :-
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 0 ; i < n; i++){
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest =(5 * (cand *cand)) + 4;
int bTest = (5 * (cand *cand)) - 4;
int sqrt1 = (int)Math.sqrt(aTest);// Taking square root of aTest, taking into account only the integer part.
int sqrt2 = (int)Math.sqrt(bTest);// Taking square root of bTest, taking into account only the integer part.
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
But its not clearing all the test cases? What bug fixes I can do ?
A much simpler solution is based on the fact that there are only 49 Fibonacci numbers below 10^10.
Precompute them and store them in an array or hash table for existency checks.
The runtime complexity will be O(log N + T):
Set<Long> nums = new HashSet<>();
long a = 1, b = 2;
while (a <= 10000000000L) {
nums.add(a);
long c = a + b;
a = b;
b = c;
}
// then for each query, use nums.contains() to check for Fibonacci-ness
If you want to go down the perfect square route, you might want to use arbitrary-precision arithmetics:
// find ceil(sqrt(n)) in O(log n) steps
BigInteger ceilSqrt(BigInteger n) {
// use binary search to find smallest x with x^2 >= n
BigInteger lo = BigInteger.valueOf(1),
hi = BigInteger.valueOf(n);
while (lo.compareTo(hi) < 0) {
BigInteger mid = lo.add(hi).divide(2);
if (mid.multiply(mid).compareTo(x) >= 0)
hi = mid;
else
lo = mid.add(BigInteger.ONE);
}
return lo;
}
// checks if n is a perfect square
boolean isPerfectSquare(BigInteger n) {
BigInteger x = ceilSqrt(n);
return x.multiply(x).equals(n);
}
Your tests for perfect squares involve floating point calculations. That is liable to give you incorrect answers because floating point calculations typically give you inaccurate results. (Floating point is at best an approximate to Real numbers.)
In this case sqrt(n*n) might give you n - epsilon for some small epsilon and (int) sqrt(n*n) would then be n - 1 instead of the expected n.
Restructure your code so that the tests are performed using integer arithmetic. But note that N < 1010 means that N2 < 1020. That is bigger than a long ... so you will need to use ...
UPDATE
There is more to it than this. First, Math.sqrt(double) is guaranteed to give you a double result that is rounded to the closest double value to the true square root. So you might think we are in the clear (as it were).
But the problem is that N multiplied by N has up to 20 significant digits ... which is more than can be represented when you widen the number to a double in order to make the sqrt call. (A double has 15.95 decimal digits of precision, according to Wikipedia.)
On top of that, the code as written does this:
int cand = sc.nextInt();
int aTest = (5 * (cand * cand)) + 4;
For large values of cand, that is liable to overflow. And it will even overflow if you use long instead of int ... given that the cand values may be up to 10^10. (A long can represent numbers up to +9,223,372,036,854,775,807 ... which is less than 1020.) And then we have to multiply N2 by 5.
In summary, while the code should work for small candidates, for really large ones it could either break when you attempt to read the candidate (as an int) or it could give the wrong answer due to integer overflow (as a long).
Fixing this requires a significant rethink. (Or deeper analysis than I have done to show that the computational hazards don't result in an incorrect answer for any large N in the range of possible inputs.)
According to this link a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square so you can basically do this check.
Hope this helps :)
Use binary search and the Fibonacci Q-matrix for a O((log n)^2) solution per test case if you use exponentiation by squaring.
Your solution does not work because it involves rounding floating point square roots of large numbers (potentially large enough not to even fit in a long), which sometimes will not be exact.
The binary search will work like this: find Q^m: if the m-th Fibonacci number is larger than yours, set right = m, if it is equal return true, else set left = m + 1.
As it was correctly said, sqrt could be rounded down. So:
Even if you use long instead of int, it has 18 digits.
even if you use Math.round(), not simply (int) or (long). Notice, your function wouldn't work correctly even on small numbers because of that.
double have 14 digits, long has 18, so you can't work with squares, you need 20 digits.
BigInteger and BigDecimal have no sqrt() function.
So, you have three ways:
write your own sqrt for BigInteger.
check all numbers around the found unprecise double sqrt() for being a real sqrt. That means also working with numbers and their errors simultaneously. (it's horror!)
count all Fibonacci numbers under 10^10 and compare against them.
The last variant is by far the simplest one.
Looks like to me the for-loop doesn't make any sense ?
When you remove the for-loop for me the program works as advertised:
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest = 5 * cand *cand + 4;
int bTest = 5 * cand *cand - 4;
int sqrt1 = (int)Math.sqrt(aTest);
int sqrt2 = (int)Math.sqrt(bTest);
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
You only need to test for a given candidate, yes? What is the for loop accomplishing? Could the results of the loop be throwing your testing program off?
Also, there is a missing } in the code. It will not run as posted without adding another } at the end, after which it runs fine for the following input:
10 1 2 3 4 5 6 7 8 9 10
IsFibo
IsFibo
IsFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
Taking into account all the above suggestions I wrote the following which passed all test cases
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long[] fib = new long[52];
Set<Long> fibSet = new HashSet<>(52);
fib[0] = 0L;
fib[1] = 1L;
for(int i = 2; i < 52; i++){
fib[i] = fib[i-1] + fib[i - 2];
fibSet.add(fib[i]);
}
int n = sc.nextInt();
long cand;
for(int i = 0; i < n; i++){
cand = sc.nextLong();
if(cand < 0){System.out.println("IsNotFibo");continue;}
if(fibSet.contains(cand)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
I wanted to be on the safer side hence I choose 52 as the number of elements in the Fibonacci sequence under consideration.

BigInteger: count the number of decimal digits in a scalable method

I need the count the number of decimal digits of a BigInteger. For example:
99 returns 2
1234 returns 4
9999 returns 4
12345678901234567890 returns 20
I need to do this for a BigInteger with 184948 decimal digits and more. How can I do this fast and scalable?
The convert-to-String approach is slow:
public String getWritableNumber(BigInteger number) {
// Takes over 30 seconds for 184948 decimal digits
return "10^" + (number.toString().length() - 1);
}
This loop-devide-by-ten approach is even slower:
public String getWritableNumber(BigInteger number) {
int digitSize = 0;
while (!number.equals(BigInteger.ZERO)) {
number = number.divide(BigInteger.TEN);
digitSize++;
}
return "10^" + (digitSize - 1);
}
Are there any faster methods?
Here's a fast method based on Dariusz's answer:
public static int getDigitCount(BigInteger number) {
double factor = Math.log(2) / Math.log(10);
int digitCount = (int) (factor * number.bitLength() + 1);
if (BigInteger.TEN.pow(digitCount - 1).compareTo(number) > 0) {
return digitCount - 1;
}
return digitCount;
}
The following code tests the numbers 1, 9, 10, 99, 100, 999, 1000, etc. all the way to ten-thousand digits:
public static void test() {
for (int i = 0; i < 10000; i++) {
BigInteger n = BigInteger.TEN.pow(i);
if (getDigitCount(n.subtract(BigInteger.ONE)) != i || getDigitCount(n) != i + 1) {
System.out.println("Failure: " + i);
}
}
System.out.println("Done");
}
This can check a BigInteger with 184,948 decimal digits and more in well under a second.
This looks like it is working. I haven't run exhaustive tests yet, n'or have I run any time tests but it seems to have a reasonable run time.
public class Test {
/**
* Optimised for huge numbers.
*
* http://en.wikipedia.org/wiki/Logarithm#Change_of_base
*
* States that log[b](x) = log[k](x)/log[k](b)
*
* We can get log[2](x) as the bitCount of the number so what we need is
* essentially bitCount/log[2](10). Sadly that will lead to inaccuracies so
* here I will attempt an iterative process that should achieve accuracy.
*
* log[2](10) = 3.32192809488736234787 so if I divide by 10^(bitCount/4) we
* should not go too far. In fact repeating that process while adding (bitCount/4)
* to the running count of the digits will end up with an accurate figure
* given some twiddling at the end.
*
* So here's the scheme:
*
* While there are more than 4 bits in the number
* Divide by 10^(bits/4)
* Increase digit count by (bits/4)
*
* Fiddle around to accommodate the remaining digit - if there is one.
*
* Essentially - each time around the loop we remove a number of decimal
* digits (by dividing by 10^n) keeping a count of how many we've removed.
*
* The number of digits we remove is estimated from the number of bits in the
* number (i.e. log[2](x) / 4). The perfect figure for the reduction would be
* log[2](x) / 3.3219... so dividing by 4 is a good under-estimate. We
* don't go too far but it does mean we have to repeat it just a few times.
*/
private int log10(BigInteger huge) {
int digits = 0;
int bits = huge.bitLength();
// Serious reductions.
while (bits > 4) {
// 4 > log[2](10) so we should not reduce it too far.
int reduce = bits / 4;
// Divide by 10^reduce
huge = huge.divide(BigInteger.TEN.pow(reduce));
// Removed that many decimal digits.
digits += reduce;
// Recalculate bitLength
bits = huge.bitLength();
}
// Now 4 bits or less - add 1 if necessary.
if ( huge.intValue() > 9 ) {
digits += 1;
}
return digits;
}
// Random tests.
Random rnd = new Random();
// Limit the bit length.
int maxBits = BigInteger.TEN.pow(200000).bitLength();
public void test() {
// 100 tests.
for (int i = 1; i <= 100; i++) {
BigInteger huge = new BigInteger((int)(Math.random() * maxBits), rnd);
// Note start time.
long start = System.currentTimeMillis();
// Do my method.
int myLength = log10(huge);
// Record my result.
System.out.println("Digits: " + myLength+ " Took: " + (System.currentTimeMillis() - start));
// Check the result.
int trueLength = huge.toString().length() - 1;
if (trueLength != myLength) {
System.out.println("WRONG!! " + (myLength - trueLength));
}
}
}
public static void main(String args[]) {
new Test().test();
}
}
Took about 3 seconds on my Celeron M laptop so it should hit sub 2 seconds on some decent kit.
I think that you could use bitLength() to get a log2 value, then change the base to 10.
The result may be wrong, however, by one digit, so this is just an approximation.
However, if that's acceptable, you could always add 1 to the result and bound it to be at most. Or, subtract 1, and get at least.
You can first convert the BigInteger to a BigDecimal and then use this answer to compute the number of digits. This seems more efficient than using BigInteger.toString() as that would allocate memory for String representation.
private static int numberOfDigits(BigInteger value) {
return significantDigits(new BigDecimal(value));
}
private static int significantDigits(BigDecimal value) {
return value.scale() < 0
? value.precision() - value.scale()
: value.precision();
}
This is an another way to do it faster than Convert-to-String method. Not the best run time, but still reasonable 0.65 seconds versus 2.46 seconds with Convert-to-String method (at 180000 digits).
This method computes the integer part of the base-10 logarithm from the given value. However, instead of using loop-divide, it uses a technique similar to Exponentiation by Squaring.
Here is a crude implementation that achieves the runtime mentioned earlier:
public static BigInteger log(BigInteger base,BigInteger num)
{
/* The technique tries to get the products among the squares of base
* close to the actual value as much as possible without exceeding it.
* */
BigInteger resultSet = BigInteger.ZERO;
BigInteger actMult = BigInteger.ONE;
BigInteger lastMult = BigInteger.ONE;
BigInteger actor = base;
BigInteger incrementor = BigInteger.ONE;
while(actMult.multiply(base).compareTo(num)<1)
{
int count = 0;
while(actMult.multiply(actor).compareTo(num)<1)
{
lastMult = actor; //Keep the old squares
actor = actor.multiply(actor); //Square the base repeatedly until the value exceeds
if(count>0) incrementor = incrementor.multiply(BigInteger.valueOf(2));
//Update the current exponent of the base
count++;
}
if(count == 0) break;
/* If there is no way to multiply the "actMult"
* with squares of the base (including the base itself)
* without keeping it below the actual value,
* it is the end of the computation
*/
actMult = actMult.multiply(lastMult);
resultSet = resultSet.add(incrementor);
/* Update the product and the exponent
* */
actor = base;
incrementor = BigInteger.ONE;
//Reset the values for another iteration
}
return resultSet;
}
public static int digits(BigInteger num)
{
if(num.equals(BigInteger.ZERO)) return 1;
if(num.compareTo(BigInteger.ZERO)<0) num = num.multiply(BigInteger.valueOf(-1));
return log(BigInteger.valueOf(10),num).intValue()+1;
}
Hope this will helps.

Java - Add all odd numbers strange behaviour

I am doing a maths challenge for project euler and i have come across a strange problem when running the program. The result should be the sum of all the odd numbers up to 10,000,000 but i get a negative number, what am i doing wrong?
package program;
import java.util.*;
public class MainClass {
/**
* #param args
*/
public static void main(String[] args) {
int total = 0;
for (int counter = 1; counter < 10000000; counter++) {
if (!((counter % 2) == 0)) {
total+=counter;
}
}
System.out.println(total);
}
}
Use a long instead of an int. You're getting a negative number due to integer overflow.
The int variable can't hold the total because the total is too big. At some point in the loop, you're getting an integer overflow and it's "rolling over" to a negative number:
You need a long.
A matter of style and efficiency, I'd change the code to iterate by 2 so that you don't need the test for oddness:
public static void main(String[] args) {
long total = 0;
for (int counter = 1; counter < 10000000; counter += 2) { // iterate by 2
total += counter;
}
System.out.println(total);
}
You should use long total = 0; instead of int total = 0; int in java is 4 bytes and ranges from -2,147,483,648 to 2,147,483,647.
so 2,147,483,647 + 1 = -2,147,483,648
The total for this loop comes out to be 25,000,000,000,000 which can be accommodated by long
Just to throw in the more clever solution to this problem (MATH! yay).
You can solve this much easier, you just need to know that the sum of odd numbers from 1..2n-1 is equal to the square of n. It's pretty easy to prove this with induction for those who want to try.
Anyways this means that the sum from 1..X is equal to: ((X + 1) / 2)**2

Categories