How does recursion works in this code to find GCD? - java

I came across this codes for finding the GCD of an array of numbers from here
//Function to return gcd of a and b
static int gcd(int a, int b) {
if (a == 0) {
return b;
}
return gcd(b % a, a);
}
// Function to find gcd of array of
// numbers
static int findGCD(int arr[], int n) {
int result = arr[0];
for (int i = 1; i < n; i++) {
result = gcd(arr[i], result);
}
return result;
}
The method gcd uses a recursive call gcd(b % a, a). So how does this recursive call works? I know the basics of how a recursion works but I am a little confused on how the gcd method on this piece of code uses recursion. Can anyone please explain to me simply, how the gcd method works in this code?

Let's take two numbers 24 and 60, and you called the function as gcd(24, 60), then the function stack executes as follows,
gcd(24,60) => 60%24 = 12
gcd(24,12) => 12%24 = 12 (Switch happens)
gcd(12,24) => 24%12 = 0
gcd(0 ,12) => terminates
So switch that happens at step two is the important one because the call basically swaps two numbers, just like you do in an iterative way, think of it like shorthand way.
I could take the same example with 60 and 24 as the first call, then gcd(60,24) would execute as
gcd(60,24) => 24%60 = 24 (Switch happens)
gcd(24,60) => 60%24 = 12 and this follows the same pattern as the above
Here the switch happens because the functions send b%a to the next function as a and a to the function as b.

Given two numbers, 12 and 8:
gcd(12,8) calculates b%a = 12%8 = 4 and then calls gcd(4, 8). It does not return yet, because that last call is not completed yet.
gcd(4,8) calculates b%a = 8%4 = 0 and then calls gcd(0,4). That one does not return yet as well, because that call is active.
gcd(0,4) branches into the first if-statement and returns 4.
That defines the return value of gcd(4,8), so the pending call returns 4 as well.
That again defines the return value of gcd(12,8), so the final result is still 4.
The math behind it is also interesting.
I think the main question is: why can we reduce gcd(12,8) to gcd(4,8)?
We assume that there is any result g that can divide 12 without a remainder and 8 without a remainder.
We can split the 12 into g*n (4*3) and 8 into g*m (4*2).
Next, we can say 12-8 = gn-gm = g*(n-m) (4*(3-2)=4). Therefore g does not only divide 12 and 8 without remainder, but also 12-8 (4).
You can do that for even lower numbers: 12-8-8 = gn-gm-gm=g(n-m-m) (4*(3-2-2)=-4). And so on.
The same is true for larger numbers: 12+8 = gn+gm = g*(n+m) (4*(3+2)=20). And you can repeat that by adding 8 numerous times.
The smallest positive number you can get by this approch is 12%8, because you can subtract 8 from 12 for so many times until its remainder is left.

To help understand recursive methods it is often useful to place print statements in key locations so you can follow what is happening.
By calling the method with specifically chosen prime factors, it is easy to ensure a particular gcd.
In the example below, 3 is the only common factor so it will be the gcd of the two numbers.
public class RecursiveGCD {
public static void main(String[] args) {
System.out.println("GCD = " + gcd(2 * 3 * 4 * 4 * 5, 3 * 7 * 11));
}
public static int gcd(int a, int b) {
System.out.println("\nFinding gcd of a=" + a + " and b=" + b);
if (a == 0) {
System.out.println("a == 0 so returning b (gcd) = " + b);
return b;
}
System.out.println(
"Remainder non-zero, calling with gcd(b % a, a) = gcd(" + (b % a)
+ ", " + a + ").");
return gcd(b % a, a);
}
}

Related

Minimum number of powers of 2 to get an Integer?

I was asked below question in an interview:
Every number can be described via the addition and subtraction of powers of 2. For example, 29 = 2^0 + 2^2 + 2^3 + 2^4.
Given an int n, return minimum number of additions
and subtractions of 2^i to get n.
Example 1:
Input: 15
Output: 2
Explanation: 2^4 - 2^0 = 16 - 1 = 15
Example 2:
Input: 8
Output: 1
Example 3:
Input: 0
Output: 0
Below is what I got but is there any way to improve this or is there any better way to solve above problem?
public static int minPowerTwo(int n) {
if (n == 0) {
return 0;
}
if (Integer.bitCount(n) == 1) {
return 1;
}
String binary = Integer.toBinaryString(n);
StringBuilder sb = new StringBuilder();
sb.append(binary.charAt(0));
for (int i = 0; i < binary.length() - 1; i++) {
sb.append('0');
}
int min = Integer.parseInt(sb.toString(), 2);
sb.append('0');
int max = Integer.parseInt(sb.toString(), 2);
return 1 + Math.min(minPowerTwo(n - min), minPowerTwo(max - n));
}
Well... we can deduce that each power of two should be used only once, because otherwise you can get the same result a shorter way, since 2x + 2x = 2x+1, -2x - 2x = -2x+1, and 2x - 2x = 0.
Considering the powers used in order, each one has to change the corresponding bit from an incorrect value to the correct value, because there will be no further opportunities to fix that bit, since each power is used only once.
When you need to add or subtract, the difference is what happens to the higher bits:
000000 000000 111100 111100
+ 100 - 100 + 100 - 100
------ ------ ------ ------
000100 111100 000000 111000
One way, all the higher bits are flipped. The other way they are not.
Since each decision can independently determine the state of all the higher bits, the consequences of choosing between + or - are only relevant in determining the next power of 2.
When you have to choose + or -, one choice will correct 1 bit, but the other choice will correct 2 bits or more, meaning that the next bit that requires correction will be higher.
So, this problem has a very straightforward solution with no dynamic programming or searching or anything like that:
Find the smallest power of 2 that needs correction.
Either add it or subtract it. Pick the option that corrects 2 bits.
Repeat until all the bits are correct
in java, that would look like this. Instead of finding the operations required to make the value, I'll find the operations required to change the value to zero, which is the same thing with opposite signs:
int minPowersToFix(int val) {
int result = 0;
while(val!=0) {
++result;
int firstbit = val&-val; //smallest bit that needs fixed
int pluscase = val+firstbit;
if ((pluscase & (firstbit<<1)) == 0) {
val+=firstbit;
} else {
val-=firstbit;
}
}
return result;
}
And, here is a test case to check whether a solution is correct, written in Java.
(It was written for my solution, which is proven not correct in some case, so I removed that answer, but the test case is still relevant.)
Matt Timmermans's answer passes all the test cases, including negative numbers.
And, Integer.bitCount(val ^ (3 * val)) passes most of them, except when input is Integer.MAX_VALUE.
Code
MinCountOf2PowerTest.java
import org.testng.Assert;
import org.testng.annotations.Test;
public class MinCountOf2PowerTest {
#Test
public void testPositive() {
// no flip,
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01010001", 2)), 3);
// flip,
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0111", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01111", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.MAX_VALUE), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01101", 2)), 3);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011011", 2)), 3);
// flip, there are multiple flippable location,
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0100000111", 2)), 3);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("010010000000111", 2)), 4);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0100100000001111111", 2)), 4);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("010011000000001111111", 2)), 5);
}
#Test
public void testZero() {
Assert.assertEquals(MinCountOf2Power.minCount(0), 0);
}
#Test
public void testNegative() {
Assert.assertEquals(MinCountOf2Power.minCount(-1), 1);
Assert.assertEquals(MinCountOf2Power.minCount(-9), 2);
Assert.assertEquals(MinCountOf2Power.minCount(-100), 3);
}
// a positive number has the same result as its negative number,
#Test
public void testPositiveVsNegative() {
for (int i = 1; i <= 1000; i++) {
Assert.assertEquals(MinCountOf2Power.minCount(i), MinCountOf2Power.minCount(-i));
}
Assert.assertEquals(MinCountOf2Power.minCount(Integer.MAX_VALUE), MinCountOf2Power.minCount(-Integer.MAX_VALUE));
}
// corner case - ending 0,
#Test
public void testCornerEnding0() {
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01110", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011110", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("011100", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("0111000", 2)), 2);
Assert.assertEquals(MinCountOf2Power.minCount(Integer.parseInt("01110000", 2)), 2);
}
// input from OP's question, refer: https://stackoverflow.com/questions/57797157
#Test
public void testOpInput() {
Assert.assertEquals(MinCountOf2Power.minCount(15), 2);
Assert.assertEquals(MinCountOf2Power.minCount(8), 1);
Assert.assertEquals(MinCountOf2Power.minCount(0), 0);
}
}
Tips:
It's written in Java, and use TestNG.
But you can use JUnit instead simply by replacing the import statement, I guess.
Or translate to other languages by coping the input / output value pairs with specific syntax.
I also found that a positive integer always has the same result as its negative number.
And there is a test case included to proved that.
I wrote this algorithm to solve the problem.
Given N a positive integer:
Find the highest power of 2 A and the lowest power of 2 B, such that A ≤ N ≤ B and A≠B. In other words find in what interval of
consecutive powers of 2 N belongs;
Find if N is closer to A or B, for example by comparing N with the mid value between A and B (It is their average, and since B=2×A the average is 3×A/2 or 1.5×A)
If N is closer to the lower bound (A) than N = A + δ: Append "subtract B" to the explanation message;
If N is closer to the higher bound (B) than N = B - δ: Append "add A" to the explanation message;
Replace N with δ and repeat
The number of iterations minus 1 is the solution you are looking for.
To solve step 1 I wrote this support method that returns the closest power of 2 that is smaller than input, that is A (and we can get B because it is just the double of A)
public int getClosestLowerboundPowerof2 (int n)
{
int i = 1;
while (i<=n/2){
i*=2;
}
return i;
}
The rest is done here:
int operations;
String explanation = "";
if (input>0){
operations = -1;
int n = input, a;
while (n >= 1) {
operations++;
a = getClosestLowerboundPowerof2(n);
if (n > a*1.5) {
explanation += " - "+ a * 2;
n = a * 2 - n;
} else {
explanation += " + " + a;
n -= a;
}
}
System.out.println(input + " = " + explanation.substring(3,explanation.length()) + ", that " + ((operations==1)?"is":"are") + " "+ operations + " operation" + ((operations==1)?"":"s"));
}
else{
System.out.println("Input must be positive");
}
As an example with input = 403 it would print:
403 = 512 - 128 + 16 + 2 + 1, that are 4 operations
Hope I helped!
NOTE: I first misinterpreted the question so I put effort in writing a detailed answer to the wrong problem...
I'm keeping here the original answer because it may be interesting for somebody.
The problem is actually a mathematical argument: how to convert a
number from base 10 to base 2, and they just asked you to implement
an algorithm for that.
Here some theory about this concept and here a method for
reference.
Programmatically I'm interpreting the problem as "Given an integer
print a string of its representation in base 2". For instance given
100 print 2^6 + 2^5 + 2^2. As the linked wiki on radixes explains,
that there is no need for subtractions, so there will only be
additions.
The shortest way to do is to start from n, halve it at each iteration
(i), and write 2^i only if this number (m) is odd. This is tested
with modulo operator (% in java). So the method will be just
this:
public String from10to2(int n){
String str = "";
for (int m = n, i=0; m>=1; m/=2, i++){
str = ((m%2==1)?"+ 2^"+i+" ":"")+str; //"adds '+ 2^i' on top of the string when m is odd, keep str the same otherwise
}
return str.substring(2,str.length()); //debug to remove " + " at the start of the string
}
The content of the for may look inintuitive because I put effort to
make the code as short as possible.
With little effort my method can be generalized to convert a number in
base 10 to any base:
public String baseConverter(int targetBase, int decimalNumber){
String str = "";
for (int m = decimalNumber, i=0; m>=1; m/=targetBase, i++){
str = ((m%targetBase==1)?"+ "+targetBase+"^"+i+" ":"")+str; //"adds '+ x^i' on top of the string when m is odd, keep str the same
otherwise
}
return str.substring(2,str.length()); //debug to remove " + " at the start of the string
}
PS: I didn't use StringBuilder because it's not conceived to append a string on the start. The use of the String concatenation as I
did is argument of debate (someone approve it, other don't).
I guess
For example, 29 = 2^0 + 2^2 + 2^3 + 2^4
is not a correct example in the context of this question. As far as I understand, I should be able to do like
29 = 2^5 - 2^2 + 2^0
Alright, basically this is a math problem. So if math isn't your best suit like me then i would advise you to consider logarithm in the first place whenever you see exponentials in a question. Sometimes it is very useful like in this case since it reduces this problem to a sort of coin change problem with dynamical denominators and also subtraction is allowed.
First I need to find the biggest n that's close to the target.
Lets find the exact n value in 2^n = 29 which is basically log
(2^n) = log 29, which is n log 2 = log 29 so n = log 29 / log
2. Which happens to be 4.857980995127573 and now i know that i
will start with by rounding it to 5.
2^5 is an overshoot. Now i need to reach 32-29 = 3 and also since 32 > 29 the result, 2^2 will be subtracted.
Now we have 2^5 - 2^2 which is 28 and less than 29. Now we need to add the next result and our target is 1.
Ok here is a simple recursive code in JS. I haven't fully tested but seemingly applies the logic just fine.
function pot(t, pr = 0){ // target and previous result
var d = Math.abs(t - pr), // difference
n = Math.round(Math.log(d)/Math.log(2)), // the n figure
cr = t > pr ? pr + 2**n // current result
: pr - 2**n;
return t > cr ? `2^${n} + ` + pot(t, cr) // compose the string result
: t < cr ? `2^${n} - ` + pot(t, cr)
: `2^${n}`;
}
console.log(pot(29));
console.log(pot(1453));
console.log(pot(8565368));
This seems pretty trivial to solve for the cases presented in the examples, like:
0111...1
You can replace any of this pattern with just two powers; i.e.: 7 = 8 - 1 or 15 = 16 - 1 and so on.
You can also deduce that if there are less then 3 consecutive ones, you don't gain much, for example:
0110 (4 + 2)
0110 (8 - 2)
But at the same time, you don't lose anything by doing that operation; in contrast for some cases this is even beneficial:
0110110 - // 54, this has 4 powers
we can take the "last" 0110 and replace it with 1000 - 0010 (8-2) or:
0111000 - 000010 (56 - 2)
but now we can replace 0111 with just two powers : 1000 - 0001.
As such a simple "replace" algorithm can be made:
static int count(int x) {
String s = new StringBuffer(Integer.toBinaryString(x)).reverse().toString() + "0";
Pattern p = Pattern.compile("1+10");
Matcher m = p.matcher(s);
int count = 0;
while (m.find()) {
++count;
s = m.replaceFirst("1");
m = p.matcher(s);
}
return Integer.bitCount(Integer.parseInt(s, 2)) + count;
}

The difference between returning a recursive method and using a returning method? [duplicate]

This question already has answers here:
Understanding recursion [closed]
(20 answers)
Closed 5 years ago.
I am in a java class at my highschool so I am very new to writing code.
For a recursive method, how does using the word return effect the output? I assume return means and end to the program.
For this program, what would random(15) output? Would it just keep looping until inevitably c was 10 and then return 80? If possible, please break this down step by step as I am having trouble understanding it.
public int random(int c)
{
if( int c > 10)
return random(c - 1);
return c * 8;
}
How does this code differ from this code, that does not have the return keyword.
public int random(int c)
{
if( int c > 10)
random(c - 1);
return c * 8;
}
First of all I'm not sure why you need to ask this question, in fact I think you understand the concept of recursive methods quite good.
First Snippet
As you explained correctly random(15) returns a value of 80.
public static void main(String[] args) {
System.out.println("Result: " + random(15));
}
private static int random(int c) {
if (c > 10) {
System.out.println("c is greater than 10");
return random(c - 1);
}
System.out.println("multiplying c=" + c + " by 8");
return c * 8;
}
Output:
run:
c is greater than 10
c is greater than 10
c is greater than 10
c is greater than 10
c is greater than 10
multiplying c=10 by 8
Result: 80
BUILD SUCCESSFUL (total time: 0 seconds)
Just for explanation, the variable c is decreased by 1 five times and then finally multiplied by 8.
Second Snippet
I just assume that your second method should look something like this:
public static void main(String[] args) {
System.out.println("Result: " + random(15));
}
private static int random(int c) {
if (c > 10) {
System.out.println("c is greater than 10");
random(c - 1);
}
System.out.println("multiplying c=" + c + " by 8");
return c * 8;
}
This time, the output looks different and also the result is different.
Output:
run:
c is greater than 10 // method a
c is greater than 10 // b
c is greater than 10 // c
c is greater than 10 // d
c is greater than 10 // e
multiplying c=10 by 8 // --> random(c - 1); in method e
multiplying c=11 by 8 // happening in method e
multiplying c=12 by 8 // d
multiplying c=13 by 8 // c
multiplying c=14 by 8 // b
multiplying c=15 by 8 // a
Result: 120
BUILD SUCCESSFUL (total time: 0 seconds)
You can see that your variable c is decreased by 1 in each method (a - e) and then equal to 10-15. At the end only the last multiplication matters, which is 15 * 8 of course, and the result of this operation is then displayed as the result.
Cobra_8
Even though you should probably do some research about recursive methods, I'll try to explain the difference as simple as possible.
In your first method, if c > 10 then the method returns the result of the call to itself with the parameter c - 1, this means that as long as c is greater than 10, the method will get called and c will decrease by one until it's equal to 10 to then return 80 (10 * 8).
The second method does nothing special, in fact you can say that it's like only returning c * 8, why? Because you're calling the same method with c - 1 but you're not using the result and the code gets out of the if statement and goes to the return c * 8; so no matter how much is c, the result will always be c * 8.
On the other hand with the first method, it'll get called recursively until c reachs 10 and will then return 80 back to the very first call of the method (see https://introcs.cs.princeton.edu/java/23recursion/ for more informations).

I need help understanding this recursive code

the question is "Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit."
public static void main(String[] args){
System.out.println(persistence(39));
//System.out.println(persistence(999));
}
public static int persistence(long n) {
long m = 1, r = n;
if (r / 10 == 0) {
return 0;
}
for(r = n; r!= 0; r /=10){
m *= r % 10;
}
//System.out.println(m);
return persistence(m) + 1;
}
I understand that the if statement is for when its finally a single digit and it'll return 0. If i could get an explanation on the m variable and what its there for. What the for loop does and when it returns persistence(m) why there is a + 1 on it.
The calculation will comes likes this .
let us understand the problem statement.
Write a function, persistence, that takes in a positive parameter num
and returns its multiplicative persistence, which is the number of
times you must multiply the digits in num until you reach a single
digit."
Say : 39
which is the number of times you must multiply the digits in num
until you reach a single digit.
So, we need to do like this to satisfy the above statement.
39 = 3*9 = 27 (1 time) - persistance(39)
27 = 2*7 = 14 (2rd time) - persistance(27)
14 = 1*4 = 4 (3rd time)- persistance(14)
So, according to the problem statement we come to the single digit.
you can take reference of the below, understand it .
why there is a + 1 on it.
to count the number of times the recursive function done the calculation.

How to use Euclid's algorithm to find GCF/GCD?

I have created a method that allows me to find the GCF/GCD of two numbers, and although I have a working code, I don't know how or why it works. I understand Euclid's algorithm, but am not sure how the following snippet uses it.
private int gcd(int a, int b)
{
if (b == 0)
return a;
else if(a ==0)
return b;
else
return gcd(b, a % b);
}
I am especially confused on what it is returning, because why are were returning two values? And what does the a % b do? How does this use Euclid's algorithm?
"the greatest common divisor of two numbers does not change if the
larger number is replaced by its difference with the smaller number."
(wikipedia - Euclidean algorithm)
So, modulo:
Modulo returns the remainder of the integer divison between two integers. Integer division is divison without fractions or floating points. Let's denote integer division as m /\ n.
m /\ n = o;
m % n = p;
o * n + p = m;
As an example,
29 /\ 3 = 9; (3 goes - whole - into 29 9 times)
29 % 3 = 2; (the integer division of 29 into 3 has a remainder of 2)
9 * 3 + 2 = 29; (9 goes into 29 3 times (and 3 goes into 29 9 times), with a remainder of 2)
Note that if m is smaller than n (i.e. m < n), then n goes into m 0 times (m /\ n = 0), so the remainder of the integer division will be m (m % n = m, because o * n + p = m and so (0*n) + p = 0 + p = p = m);
So, how does the function work? let's try using it.
1 - gcd(m, n), m < n
So, if we start out gcd(m, n) with an m that is smaller than n, the only thing that happens on the next nested call to gcd is that the order of the arguments changes: gcd(n, m % n) = gcd(n, m);
2 - gcd(n, m), m < n
Okay, so now the first argument larger than the second.
According to euclid's algorithm, we want to do something to the larger of the two numbers. We want to replace it with the difference between it and the smaller number. We could do m - n a bunch of times. But what m % n does is the exact same as subtracting n from m as many times as possible before doing so would result in a negative number. Doing a subtraction would look like (((m - n) - n) - n) - n) and so on. But if we expand that out, we get:
m - (n * o). Because o * n + p = m, we can see that m - (n * o) = p and p = m % n. So, repeatedly subtracting the smaller from the larger is the same as doing modulo of the larger with the smaller.
In the next step, the second argument may be 0 (if n was a divisor of m). In this case, the function returns n. this is correct because n is a divisor of itself and also, as we've seen, a divisor of m.
Or, the second argument may be smaller than n. That is because the remainder of the integer divison of m into n must be smaller than n - this is because, if the remainder of the division were larger than n, then n could have fit into m one more time, which it didn't; this is an absurd result. Assuming that n is not 0, then the second argument (let's call it p) is smaller than n.
So, we are now calling gcd(n, p), where p < n.
3 - gcd(n, p), p < n
What happens now? well, we are exactly in the same place as we were in the previous paragraph. Now we just repeat that step, i.e. we will continue to call gcd(a, b), until the smaller of the two numbers that are passed into gcd(a ,b) is a divisor of the larger of the two numbers, (meaning that a % b = 0) in which case you simply return the smaller of the two numbers.
1) What does the a % b do?
% is the modulus or remainder operator in Java. The % operator returns the remainder of two numbers. For example 8 % 3 is 2 because 8 divided by 3 leaves a remainder of 2.
2) The Euclidean algorithm is based on the principle that the greatest common divisor of two numbers does not change if the larger number is replaced by its difference with the smaller number. Actually, your gcd function is used a more efficient version of the Euclidean algorithm. This version instead replacing the larger of the two numbers by its remainder when divided by the smaller of the two (with this version, the algorithm stops when reaching a zero remainder). This was proven by Gabriel Lamé in 1844 (https://en.wikipedia.org/wiki/Euclidean_algorithm)
3) Your gcd function's not returning two values, it's a recursive function. The recursive function is a function which either calls itself or is in a potential cycle of function calls. In case of your gcd function, it will be repeat until one of two parameters become zero and the gcd value is the remain parameter.
You could learn more about recursive function at this link.
http://pages.cs.wisc.edu/~calvin/cs110/RECURSION.html
Given that your question has a few components, I’ll discuss the evolution of Euclid’s classical algorithm into the recursive method you presented. Please note that the methods presented here assume that a >= b
The method below most likely implements the algorithm that you are familiar with, which repeatedly subtracts b (the smaller number) from a (the larger number), until it is no longer larger or equal to b. If a == 0, there is no remainder, giving b as the GCD. Otherwise, the values of a and b are swapped and repeated subtraction continues.
public int classic_gcd(int a, int b) {
while (true) {
while (a >= b)
a = a - b;
if (a == 0)
return b;
int c = b;
b = a;
a = c;
}
}
Since the inner while loop, essentially calculates the reminder of a divided by b, it can be replaced with the modulus operator. This greatly improves the convergence rate of the algorithm, replacing a potentially large number of subtractions with a single modulus operation. Consider finding the GCD of 12,288 and 6, which would result in over 2,000 subtraction. This improvement is shown in the modified method below.
public int mod_gcd(int a, int b) {
while (true) {
int c = a % b;
if (c == 0)
return b;
a = b;
b = c;
}
}
Lastly, the modified algorithm can be expressed as a recursive algorithm, that is, it calls upon itself, as follows:
public int recurse_gcd(int a, int b) {
if (b == 0)
return a;
else
return recurse_gcd(b, a % b);
}
This method accomplishes the same as before. However, rather than looping, the method calls itself (which if not checked is an endless loop too). The swapping of values is accomplishing by changing the order of the arguments passed to the method.
Mind you, the methods above are purely for demonstration and should not be used in production code.

More efficient solution: Project Euler #2: Even Fibonacci Numbers

Problem:
Each new term in the Fibonacci sequence is generated by adding the
previous two terms.
By starting with 1 and 2, the first 10 terms will
be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.
My code: (which works fine)
public static void main(String[] agrs){
int prevFirst=0;
int prevSecond=1;
int bound=4_000_000;
int evenSum=0;
boolean exceed=false; //when fib numbers > bound
while(!exceed){
int newFib=prevFirst + prevSecond;
prevFirst = prevSecond;
prevSecond = newFib;
if(newFib > bound){
exceed=true;
break;
}
if(newFib % 2 == 0){
evenSum += newFib;
}
}
System.out.println(evenSum);
}
I'm looking for a more efficient algorithm to do this question. Any hints?
When taking the following rules into account:
even + even = even
even + odd = odd
odd + even = odd
odd + odd = even
The parity of the first Fibonacci numbers is:
o o e o o e o o e ...
Thus basically, you simply need to do steps of three. Which is:
(1,1,2)
(3,5,8)
(13,21,34)
Given (a,b,c) this is (b+c,b+2*c,2*b+3*c).
This means we only need to store the two last numbers, and calculate given (a,b), (a+2*b,2*a+3*b).
Thus (1,2) -> (5,8) -> (21,34) -> ... and always return the last one.
This will work faster than a "filter"-approach because that uses the if-statement which reduces pipelining.
The resulting code is:
int b = 1;
int c = 2, d;
long sum = 0;
while(c < 4000000) {
sum += c;
d = b+(c<<0x01);
c = d+b+c;
b = d;
}
System.out.println(sum);
Or the jdoodle (with benchmarking, takes 5 microseconds with cold start, and on average 50 nanoseconds, based on the average of 1M times). Of course the number of instructions in the loop is larger. But the loop is repeated one third of the times.
You can't improve it much more, any improvement that you'll do will be negligible as well as depended on the OS you're running on.
Example:
Running your code in a loop 1M times on my Mac too 73-75ms (ran it a few times).
Changing the condition:
if(newFib % 2 == 0){
to:
if((newFib & 1) == 0){
and running it again a few times I got 51-54ms.
If you'll run the same thing on a different OS you might (and
probably will) get different results.
even if we'll consider the above as an improvement, divide ~20ms in 1M and the "improvement" that you'll get for a single run is meaningless (~20 nanos).
assuming consecutive Fibonacci numbers
a, b,
c = a + b,
d = a + 2b,
e = 2a + 3b,
f = 3a + 5b,
g = 5a + 8b = a + 4(a + 2b) = a + 4d,
it would seem more efficient to use
ef0 = 0, ef1 = 2, efn = efn-2 + 4 efn-1
as I mentioned in my comment there is really no need to further improvement.
I did some measurements
looped 1000000 times the whole thing
measure time in [ms]
ms / 1000000 = ns
so single pass times [ns] are these:
[176 ns] - exploit that even numbers are every third
[179 ns] - &1 instead of %2
[169 ns] - &1 instead of %2 and eliminated if by -,^,&
[edit1] new code
[105 ns] - exploit that even numbers are every third + derived double iteration of fibonaci
[edit2] new code
[76 ns] - decreased operand count to lower overhead and heap trashing
the last one clearly wins on mine machine (although I would expect that the first one will be best)
all was tested on Win7 x64 AMD A8-5500 3.2GHz
App with no threads 32-bit compiler BDS2006 Trubo C++
1,2 are nicely mentioned in Answers here already so I comment just 3:
s+=a&(-((a^1)&1));
(a^1) negates lovest bit
((a^1)&1) is 1 for even and 0 for odd a
-((a^1)&1)) is -1 for even and 0 for odd a
-1 is 0xFFFFFFFF so anding number by it will not change it
0 is 0x00000000 so anding number by it will be 0
hence no need for if
also instead of xor (^) you can use negation (!) but that is much slower on mine machine
OK here is the code (do not read further if you want to code it your self):
//---------------------------------------------------------------------------
int euler002()
{
// Each new term in the Fibonacci sequence is generated by adding the previous two terms.
// By starting with 1 and 2, the first 10 terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
// By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
int a,a0=0,a1=1,s=0,N=4000000;
/*
//1. [176 ns]
a=a0+a1; a0=a1; a1=a; // odd
a=a0+a1; a0=a1; a1=a; // even
for (;a<N;)
{
s+=a;
a=a0+a1; a0=a1; a1=a; // odd
a=a0+a1; a0=a1; a1=a; // odd
a=a0+a1; a0=a1; a1=a; // even
}
//2. [179 ns]
for (;;)
{
a=a0+a1; a0=a1; a1=a;
if (a>=N) break;
if ((a&1)==0) s+=a;
}
//3. [169 ns]
for (;;)
{
a=a0+a1; a0=a1; a1=a;
if (a>=N) break;
s+=a&(-((a^1)&1));
}
//4. [105 ns] // [edit1]
a0+=a1; a1+=a0; a=a1; // 2x
for (;a<N;)
{
s+=a; a0+=a1; a1+=a0; // 2x
a=a0+a1; a0=a1; a1=a; // 1x
}
*/
//5. [76 ns] //[ edit2]
a0+=a1; a1+=a0; // 2x
for (;a1<N;)
{
s+=a1; a0+=a1; a1+=a0; // 2x
a=a0; a0=a1; a1+=a; // 1x
}
return s;
}
//---------------------------------------------------------------------------
[edit1] faster code add
CommuSoft suggested to iterate more then 1 number per iteration of fibonaci to minimize operations.
nice idea but code in his comment does not give correct answers
I tweaked a little mine so here is the result:
[105 ns] - exploit that even numbers are every third + derived double iteration of fibonaci
this is almost twice the speedup of 1. from which it is derived
look for [edit1] in code or look for //4.
[edit2] even faster code add
- just reorder of some variable and operation use for more speed
- [76 ns] decreased operand count to lower overhead and heap trashing
if you check Fibonacci series, for even numbers 2 8 34 144 610 you can see that there is a fantastic relation between even numbers, for example:
34 = 4*8 + 2,
144 = 34*4 + 8,
610 = 144*4 + 34;
this means that next even in Fibonacci can be expressed like below
Even(n)=4*Even(n-1)+E(n-2);
in Java
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int t = in.nextInt();
for(int a0 = 0; a0 < t; a0++){
long n = in.nextLong();
long a=2;
long b=8;
long c=0;
long sum=10;
while(b<n)
{
sum +=c;
c=b*4+a;
a=b;
b=c;
}
System.out.println(sum);
}
}
F(n) be the nth Fibonnaci number i.e F(n)=F(n-1)+F(n-2)
Lets say that F(n) is even, then
F(n) = F(n-1) + F(n-2) = F(n-2) + F(n-3) + F(n-2)
F(n) = 2F(n-2) + F(n-3)
--This proves the point that every third term is even (if F(n-3) is even, then F(n) must be even too)
F(n) = 2[F(n-3) + F(n-4)] + F(n-3)
= 3F(n-3) + 2F(n-4)
= 3F(n-3) + 2F(n-5) + 2F(n-6)
From eq.1:
F(n-3) = 2F(n-5) + F(n-6)
2F(n-5) = F(n-3) - F(n-6)
F(n) = 3F(n-3) + [F(n-3) - F(n-6)] + 2F(n-6)
= 4F(n-3) + F(n-6)
If the sequence of even numbers consists of every third number (n, n-3, n-6, ...)
Even Fibonacci sequence:
E(k) = 4E(k-1) + E(k-2)
Fib Sequence F= {0,1,1,2,3,5,8.....}
Even Fib Sequence E={0,2,8,.....}
CODE:
public static long findEvenFibSum(long n){
long term1=0;
long term2=2;
long curr=0;
long sum=term1+term2;
while((curr=(4*term2+term1))<=n){
sum+=curr;
term1=term2;
term2=curr;
}
return sum;
}
The answer for project Euler problem 2 is(in Java):
int x = 0;
int y = 1;
int z = x + y;
int sumeven = 0;
while(z < 4000000){
x = y;
y = z;
z = x + y;
if(z % 2 == 0){
sumeven += z; /// OR sumeven = sumeven + z
}
}
System.out.printf("sum of the even-valued terms: %d \n", sumeven);
This is the easiest answer.

Categories

Resources