How to write an efficient Fibonacci summing algorithm - java

Project Euler, problem 2: Determine the sum of the even numbers in the Fibonacci sequence up to 4 000 000. First I tried to
use a recursive algorithm for the sequence but I realized I dont have all the time in the world so I now use an iterative. It is still
extremely slow. Can I improve my code?
public class Euler2Correct {
public static int Fibonacci(int j){
/**
* Metod for returnerning number [I]j[/I] in the sequence.
*
*/
if(j<=1){
return 1;
}
else if(j==2){
return 2;
}
int tmp;
int a=2;
int b=1;
for(int k=3; k<=j; k++){
tmp=a+b;
b=a;
a=tmp;
}
return a;
}
public static void main(String[]args){
int s=0;
for(int i=2; i<4000000; i=i+3){ //Every three number is even
s = s + Fibonacci(i);
}
System.out.println(s);
}
}

You are recalculating the Fibonacci number over and over again from scratch. If you keep the running total in the Fibonacci method, you can use the previous results to prevent doing all that extra work.
Here's the modified version of your code, I tried to keep it as similar as possible
public class Euler2Correct {
public static int Fibonacci(int j) {
int tmp;
int a = 2;
int b = 1;
int total = 0;
do {
if(isEven(a)) total +=a;
tmp = a + b;
b = a;
a = tmp;
} while (a < j);
return total;
}
private static boolean isEven(int a) {
return (a & 1) == 0;
}
public static void main(String[] args) {
// Notice there is no more loop here
System.out.println(Fibonacci(4_000_000));
}
}

Related

Code wont return sum when trying to get all numbers between 1 to n added together

I am trying to get the code to to add all numbers from 1 to n, however when i try and return the sum, i keep getting an error saying it cant be resolved to a variable.
public class methodCalls {
public static void main(String[] args) {
}
public static int sum(int n) {
//int sum;
for (int i=1; i<=n;i++) {
int sum = 0;
sum +=1;
}
return sum;
}
}
public class methodCalls {
public static void main(String[] args) {
}
public static int sum(int n) {
int sum = 0;
for (int i=1; i<=n;i++) {
//int sum = 0;
sum +=1;
}
return sum;
}
}
The sum variable needs to be outside of loop, because for each loop, the variable will be reinitialized. Secondly, the error you mention is because you needs to declare default value of method level variable.
EDIT: I like #Elliot's solution in comments above better.
The variable sum is declared inside the for loop and its scope is within the loop. The variable won't be accessible outside of the loop and that's why you are getting the error that you mentioned.
Please try this :
public static int sum(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += 1;
}
return sum;
}
You are trying the return the sum variable which is out of scope there.
Other that that to get the sum from 1 to n you need to do this sum = sum + i
public static int sum(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum = sum+i;
}
return sum;
}

Recursive function to return the average of the digits in a number

I'm trying to create a recursive function that returns the average of the digits in a number. For example the average of the number 123 is 2.
I know how to write a function that sums the digits.
public static int sum (int n) {
if (n<10)
return n;
return n%10 + sum(n/10);
}
I also know how to count the digits
public static int numCount(int n) {
if (n<10)
return 1;
return 1 + numCount(n/10);
}
However I can't figure out how to calculate the average without using pre existing functions.
You can recursively iterate the array while keeping both accumulative sum and an index that shows which items were already iterated:
public class MyClass {
public static void main(String args[]) {
int[] arr = {1,2,3};
System.out.println(avg(arr)); // 2.0
}
private static double avg(int[] arr) {
return avg(arr, 0, 0);
}
private static double avg(int[] arr, int index, int sum) {
if (index == arr.length) {
return (double) sum / index;
}
return avg(arr, index + 1, sum + arr[index]);
}
}
Demo
Try this:
int recursive(int num, int startingSize) {
if(num < 10){
return num;
}
num = num % 10 + recursive(num/10, startingSize++);
return num/startingSize;
}
and for example : recursive(123, 1)
count=0;
public static int sum (int n) {
count++;
if (n<10)
return n;
return n%10 + sum(n/10);
}
double average = (double)sum(123)/count;
System.out.println("average:"+ average);
I mean if we are just talking numbers we don't even need recursive functions here
String s = Double(10.45).toString();
Int size = s.length();
int count = 0;
Int sum = 0;
for (int i = 0; i < size; I++ ) {
try {
sum += Integer.valueOf(s[i]);
++count;
} catch (Exception e) {}
}
return sum / count;
That should give you an. Average regardless of number, whole or real.

iterative program on java

i have this program
public static int p(int n, int m){
if(n==m) return n;
if (n<m) return p(n,m-n);
else return p(n-m,m);
}
how to put this program on iterative program with while loop.
Thanks
This code substacts the smaller of the two inputs from the larger until they are equal. This can be done with a while loop:
public static int p(int n, int m){
while (m!=n) {
if (n<m)
m -= n;
else
n -= m;
}
return n;
}

LCM (lowest common multiple) in Java

I need help with this loop. One of my course assignments is to make a LCM program.
Sample output:
(8,12) LCM is 24
(4,3) LCM is 12
(5,10,20) LCM is 20
(18,24,52) LCM is 936
(12,10,26) LCM is 780
(99,63,24) LCM is 5544
(62,16,24) LCM is 1488
I have this so far for 2 numbers but I'm not sure how to do 3 numbers. We're supposed to use methods on other classes so this is what I have for the LCM class.
public class LCM {
private int n, x, s = 1, t = 1;
public LCM()
{
n = 0;
x = 0;
s = 1;
t = 1;
}
public int lcmFind(int i, int y) {
for (n = 1;; n++) {
s = i * n;
for (x = 1; t < s; x++) {
t = y * x;
}
if (s == t)
break;
}
return (s);
}
}
If you want to get LCM of 3+ numbers you can use your method lcmFind in following way:
int a = 2;
int b = 3;
int c = 5;
LCM l = new LCM();
int lcm = l.lcmFind(l.lcmFind(a, b), c);
Reccomendations:
Make n,x, s and t variables local in lcmFind. Because you need them ONLY in lcmFind method and you need to reset their values in every invocation of lcmFind.
Make your lcmFind method static. You don't need to instantiate new object in order to calc lcm. This way you can use it like LCM.lcmFind(3,4), or even better rename method and use something like LCM.find(3,4).
EDIT
If you need to make method that takes variable number of argument you should check varargs. So you'll get something like:
public int lcmFind(int.. args) {
// args is actually array of ints.
// calculate lcm of all values in array.
// usage: lcmFind(1,4) or lcmFind(1,5,6,3)
}
You can use your first version of lcmFind that takes 2 arguments and calculate lcm of many values using it.
EDIT 2
If you need only 2 and 3-args version of lcmFind than you can just add 3-arg version:
public int lcmFind(int a, int b, int c) {
return lcmFind(lcmFind(a, b), c);
}
I found this link and I guess this is most simple and clean solution:
/**
* Calculate Lowest Common Multiplier
*/
public static int LCM(int a, int b) {
return (a * b) / GCF(a, b);
}
/**
* Calculate Greatest Common Factor
*/
public static int GCF(int a, int b) {
if (b == 0) {
return a;
} else {
return (GCF(b, a % b));
}
}
try
public int lcm(int... a) {
for (int m = 1;; m++) {
int n = a.length;
for (int i : a) {
if (m % i != 0) {
break;
}
if (--n == 0) {
return m;
}
}
}
}
public static int gcd(int a, int b){
return (b == 0) ? a : gcd(b, a % b);
}
public static int gcd(int... args){
int r = args[0];
int i = 0;
while(i < args.length - 1)
r = gcd(r,args[++i]);
return r;
}
public static int lcm(int a, int b){
return a * b / gcd(a,b);
}
public static int lcm(int... args){
int r = args[0];
int i = 0;
while(i < args.length - 1)
r = lcm(r,args[++i]);
return r;
}
static int getLCM(int a,int b)
{
int x;
int y;
if(a<b)
{
x=a;
y=b;
}
else
{
x=b;
y=a;
}
int i=1;
while(true)
{
int x1=x*i;
int y1=y*i;
for(int j=1;j<=i;j++)
{
if(x1==y*j)
{
return x1;
}
}
i++;
}
}
I think you have the answer already, since it's an old post. still posting my answer. Below is the code to find the LCM for an array:
import java.util.Arrays;
import java.util.Scanner;
public class ArrayEqualAmz {
static int lcm =1;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int [] arr = new int[n];
for(int i=0; i<n; i++){
arr[i] = sc.nextInt();
}
System.out.println("lcm = "+lcm(arr));
}
// find the factor
public static int divisor(int x[]){
Arrays.sort(x);
int num=0;
for(int i=x.length-1; i>=0; i--){
if(x[i] != 1 )
num=x[i];
}
for(int j=2; j<=num; j++){
if(num%j==0){
return j;}
}
return num;
}
//finding the lcm
public static int lcm(int arr[]){
while(true){
int j = divisor(arr);
if(j==0){break;}
lcm = lcm*j;
for(int i=0; i<arr.length; i++){
if(arr[i]%j==0){
arr[i] = arr[i]/j;}
System.out.print(arr[i]+",");
}
System.out.println( " factor= "+lcm);
return lcm(arr);
}
return lcm;
}
}
Try this
int n1 = 72, n2 = 120, lcm;
// maximum number between n1 and n2 is stored in lcm
lcm = (n1 > n2) ? n1 : n2;
// Always true
while(true)
{
if( lcm % n1 == 0 && lcm % n2 == 0 )
{
System.out.printf("The LCM of %d and %d is %d.", n1, n2, lcm);
break;
}
++lcm;
}
You can re use the same function written for lcm of two numbers. Just pass one of the arguments as follows:
The function code can be like this:
public static int lcm(int num1,int num2) {
boolean flag = false;
int lcm = 0;
for(int i= 1;!flag; i++){
flag = (num1 < num2)?(num2*i)%num1==0:(num1*i)%num2==0;
lcm = num1<num2?num2*i:num1*i;
}
return lcm;
}
Call the function like this:
public static void main(String[] args) {
System.out.println("lcm "+lcm(lcm(20,80),40));
}

Find factorial of large numbers in Java

I tried to find the factorial of a large number e.g. 8785856 in a typical way using for-loop and double data type.
But it is displaying infinity as the result, may be because it is exceeding its limit.
So please guide me the way to find the factorial of a very large number.
My code:
class abc
{
public static void main (String[]args)
{
double fact=1;
for(int i=1;i<=8785856;i++)
{
fact=fact*i;
}
System.out.println(fact);
}
}
Output:-
Infinity
I am new to Java but have learned some concepts of IO-handling and all.
public static void main(String[] args) {
BigInteger fact = BigInteger.valueOf(1);
for (int i = 1; i <= 8785856; i++)
fact = fact.multiply(BigInteger.valueOf(i));
System.out.println(fact);
}
You might want to reconsider calculating this huge value. Wolfram Alpha's Approximation suggests it will most certainly not fit in your main memory to be displayed.
This code should work fine :-
public class BigMath {
public static String factorial(int n) {
return factorial(n, 300);
}
private static String factorial(int n, int maxSize) {
int res[] = new int[maxSize];
res[0] = 1; // Initialize result
int res_size = 1;
// Apply simple factorial formula n! = 1 * 2 * 3 * 4... * n
for (int x = 2; x <= n; x++) {
res_size = multiply(x, res, res_size);
}
StringBuffer buff = new StringBuffer();
for (int i = res_size - 1; i >= 0; i--) {
buff.append(res[i]);
}
return buff.toString();
}
/**
* This function multiplies x with the number represented by res[]. res_size
* is size of res[] or number of digits in the number represented by res[].
* This function uses simple school mathematics for multiplication.
*
* This function may value of res_size and returns the new value of res_size.
*/
private static int multiply(int x, int res[], int res_size) {
int carry = 0; // Initialize carry.
// One by one multiply n with individual digits of res[].
for (int i = 0; i < res_size; i++) {
int prod = res[i] * x + carry;
res[i] = prod % 10; // Store last digit of 'prod' in res[]
carry = prod / 10; // Put rest in carry
}
// Put carry in res and increase result size.
while (carry != 0) {
res[res_size] = carry % 10;
carry = carry / 10;
res_size++;
}
return res_size;
}
/** Driver method. */
public static void main(String[] args) {
int n = 100;
System.out.printf("Factorial %d = %s%n", n, factorial(n));
}
}
Hint: Use the BigInteger class, and be prepared to give the JVM a lot of memory. The value of 8785856! is a really big number.
Use the class BigInteger. ( I am not sure if that will even work for such huge integers )
Infinity is a special reserved value in the Double class used when you have exceed the maximum number the a double can hold.
If you want your code to work, use the BigDecimal class, but given the input number, don't expect your program to finish execution any time soon.
The above solutions for your problem (8785856!) using BigInteger would take literally hours of CPU time if not days. Do you need the exact result or would an approximation suffice?
There is a mathematical approach called "Sterling's Approximation
" which can be computed simply and fast, and the following is Gosper's improvement:
import java.util.*;
import java.math.*;
class main
{
public static void main(String args[])
{
Scanner sc= new Scanner(System.in);
int i;
int n=sc.nextInt();
BigInteger fact = BigInteger.valueOf(1);
for ( i = 1; i <= n; i++)
{
fact = fact.multiply(BigInteger.valueOf(i));
}
System.out.println(fact);
}
}
Try this:
import java.math.BigInteger;
public class LargeFactorial
{
public static void main(String[] args)
{
int n = 50;
}
public static BigInteger factorial(int n)
{
BigInteger result = BigInteger.ONE;
for (int i = 1; i <= n; i++)
result = result.multiply(new BigInteger(i + ""));
return result;
}
}
Scanner r = new Scanner(System.in);
System.out.print("Input Number : ");
int num = r.nextInt();
int ans = 1;
if (num <= 0) {
ans = 0;
}
while (num > 0) {
System.out.println(num + " x ");
ans *= num--;
}
System.out.println("\b\b=" + ans);
public static void main (String[] args) throws java.lang.Exception
{
BigInteger fact= BigInteger.ONE;
int factorialNo = 8785856 ;
for (int i = 2; i <= factorialNo; i++) {
fact = fact.multiply(new BigInteger(String.valueOf(i)));
}
System.out.println("Factorial of the given number is = " + fact);
}
import java.util.Scanner;
public class factorial {
public static void main(String[] args) {
System.out.println("Enter the number : ");
Scanner s=new Scanner(System.in);
int n=s.nextInt();
factorial f=new factorial();
int result=f.fact(n);
System.out.println("factorial of "+n+" is "+result);
}
int fact(int a)
{
if(a==1)
return 1;
else
return a*fact(a-1);
}
}

Categories

Resources