Generating Number Pairs and GCD in Java - java

Problem: Given A,B print the number of pairs (a,b) such that GCD(a,b)=1 and 1<=a<=A and 1<=b<=B.
Solution (Brute Force Approach)
In the below code, i have used brute force approach and it works fine. However the execution time is more 10 sec if A & B > 10^5
Alternative Solution
From my research i found out that finding prime factors of A & B will reduce the execution time considerably (< 3 sec), but i'm not sure how to apply it.
Need Help:
Can anyone help me to arrive at the result with < 3 sec execution time?
class GCD {
public static void main(String[] args) {
int A = 0, B = 0, GCD = 0, count = 0;
BigInteger B1, B2 = null;
A = Integer.parseInt(args[0]);
B = Integer.parseInt(args[1]);
for (int a = 1; a <= A; a++) {
for (int b = 1; b <= B; b++) {
B1 = BigInteger.valueOf(a);
B2 = BigInteger.valueOf(b);
GCD = calculateGCD(B1, B2);
if (GCD == 1) {
count++;
}
}
}
System.out.println(count);
}
public static int calculateGCD(BigInteger number1, BigInteger number2) {
return (number1.gcd(number2)).intValue();
}
}

I do not want to write a complete programm or something, but I want to give you some tips for speeding up your program:
gcd(a,b) = gcd(b,a) so only compute pairs (a, b) with a < b. gcd(a,a) = 1 holds only for a = 1. Also gcd(1,b) = 1 for all b, so you can start with a = 2 and a count = 1 + 2*(B-1).
compute all primefactors for all 1 < a <= A at once by using something like the Sieve of Eratosthenes. E.g. every secound number contains primefactor 2, every third the primfactor 3.
You do not need to compute the gcd. Let a contain the distinct primfactors p and q. Then you know:
There are B-a numbers to test.
Every p-th number contains also the primfactor p, every q-th primenumber also contains the primfactor q. floor( (B-a)/p ) numbers have a gcd >= p and floor( (B-a)/q ) numbers have a gcd >= q and floor( (B-a)/(p*q) ) numbers have you counted twice. So you can get the number of pairs (a,b) with a < b as
(B-a) - floor( (B-a)/p ) - floor( (B-a)/q ) + floor( (B-a)/(p*q) )
if you want also the pairs it self, you can use a for-loop and jump every step where i (for-loop counter) is divisable by any primefactor of a
I think this should speed up your program as much as you need to reach less than a second.

Related

Performance issue with CountDiv (Codility) challenge algorithm

Needing some help with the algorithm i made to solve this codility challenge :
Write a function that, given three integers A, B and K, returns the number of integers within the range [A..B] that are divisible by K.
For example, for A = 6, B = 11 and K = 2, your function should return 3, because there are three numbers divisible by 2 within the range [6..11], namely 6, 8 and 10.
A and B are integers within the range [0..2,000,000,000];
K is an integer within the range [1..2,000,000,000];
A ≤ B.
public class Solution {
public int solution(int A, int B, int K) {
int counter = 0;
ArrayList<Integer> listOfNumbersInBetween = new ArrayList<>();
for (int i = A; i <= B; i++) {
listOfNumbersInBetween.add(i);
}
for (int arrayElement : listOfNumbersInBetween) {
if (arrayElement % K == 0) {
counter++;
}
}
return counter;
}}
As you can see, my solution works perfectly but performance wise it's scoring 0% due to the time complexity O(B-A).
How can i improve this code to make it score 100%?
Using a loop is brute-force, and challenges like this cannot be done with brute-force.
Which means you have to calculate the result. Challenges like this are more often a math question more than a programming question, so put you math hat on.
So think about it. In a range of integers, calculate how many are divisible by K. If I asked you to do this manually (using a simple calculator is allowed), without using a computer to brute-force it, how would you doing it? E.g. find how many integers between 111 and 999 that are divisible by 13
Hint
Find the first number in the range that is divisible by K, and the last number in the range that is divisible by K. For the example above, that would be 117 and 988.
Now calculate how many integers are divisible by K from first to last integer, remembering to count both of them. So, how many integers between 117 and 988 are divisible by 13?
Answer: (988 - 117) / 13 + 1 = 871 / 13 + 1 = 67 + 1 = 68
One possibility is to take advantage of integer arithmetic to get rid of some edge cases. Sometimes A and B are both, neither, or one or the other is divisible by k. And just subtracting them won't really help solve the problem. So one solution is to divide each by k before subtracting them.
Say k = 7, A = 12, and B = 54.
54/7 - 12/7 = 7 - 1 = 6 (14,21,28,35,42,49)
But what if A was 14?
54/7 - 14/7 = 7 - 2 = 5 (14,21,28,35,42,49) The answer is one off. So when A is divisible by k, 1 needs to be added.
What if A and B are both divisible by k?
56/7 - 14/7 = 8 - 2 = 6 = (14,21,28,34,42,49,56). The answer is again, one off, so the special case of A being divisible by k takes care of it by adding 1
int result = (B/k - A/k) + ((A%k == 0) ? 1 : 0);
My C# solution, based on #Andreas' brilliant one. This eventually got me to 100%. Most surprising (and perhaps wrong?) is that [0, 0, 11] needs to produce a result of 1, meaning that 0 is considered divisible by 11. You'll see I had to comment out an error catcher to allow B to be zero and get me to the "expected" answer. I was surprised that (0-0)/11 didn't produce a runtime error, but it didn't.
public int solutionCountDiv4(int A, int B, int K)
{
//Errors
if (K == 0)
return 0;
//if (B == 0)
// return 0;
if (A > B)
return 0;
var first = 0;
var last = 0;
for (first = A; first <= B; first++)
{
if (first % K == 0)
break;
}
for (last = B; last >= A; last--)
{
if (last % K == 0)
break;
}
if (first > last)
return 0;
var result = (last - first) / K + 1;
return result;
}
Small correction to #Ersin's solution
int solution(int A, int B, int K)
{
auto result = B / K - (A - 1) / K;
if (A == 0 and K > 1)
result++;
return result;
}

Big numbers calculations in Java?

I have this Java code for computing some numbers
import java.math.BigInteger;
class Challenge {
final static BigInteger THOUSAND = new BigInteger("1000");
private static BigInteger compute(long n) {
BigInteger a = BigInteger.ONE;
BigInteger b = BigInteger.ONE;
for (long i = 0; i < n; i++) {
BigInteger next = b.multiply(b).add(a);
a = b;
b = next;
}
return b.mod(THOUSAND);
}
public static void main(String args[]) {
for (long n : new long[] { 1L, 2L, 5L, 10L, 20L, Long.MAX_VALUE }) {
System.out.print(n + " ---> ");
System.out.println(compute(n));
}
}
}
The code iterates several times according to given long numbers (1, 2, 5, etc), starting with a=1 and b=1:
next = (b*b)+a
a = b
b = next
It then returns b mod 1000, which it gives the last 3 digits of the calculation.
So far the codes returns:
1 ---> 2
2 ---> 5
5 ---> 783
10 ---> 968
20 ---> 351
9223372036854775807 --->
On the last one the code keeps working but the number if iterations is so big it takes forever so it never finishes.
Is there a way to do this kind of calculations faster, or to get the desired value (mod 1000 of the calculation done that many times) in a better way?
It would be a lot faster if you use an int for your calculations. However you will get a better speed up from realising that in each iteration there is only 1,000,000 possible starting values for a and b which means the longest possible sequence of values and results for a and b without repeating is one million. i.e. you can n % 1,000,000 Most likely there is a shorter repeating sequences.
The reason I say only the lower three digits of a and b matter is that you mod 1000 the result, so not matter what the upper digits of a and b are they are ignored so all you care about are the values 0 to 999
You can memorizes all possible results starting at 1,1 and it will just be a lookup.
private static long compute(long n) {
int a = 1;
int b = 1;
for (int i = 0, max = (int) (n % 1000000); i < max; i++) {
int next = b * b + a;
a = b;
b = next % 1000;
}
return b % 1000;
}
Yes, keep the running moludo for each calculation. You don't need to calculate all the digits since you are only interested in the last 3 ones.
A first improvement is to have the following:
private static BigInteger compute(long n) {
BigInteger a = BigInteger.ONE;
BigInteger b = BigInteger.ONE;
for (long i = 0; i < n; i++) {
BigInteger next = b.multiply(b).add(a);
a = b;
b = next.mod(THOUSAND); // <-- only keep the modulo each time so as not calculate all digits
}
return b.mod(THOUSAND);
}
By doing this, you can realize that you don't need BigInteger to begin with. The numbers concerned become of value low enough that they hold into a primitive datatype. As such, use a long (or even an int): it will be a lot more performant since you don't have the overhead of using a BigInteger.
private static long compute(long n) {
int a = 1;
int b = 1;
for (long i = 0; i < n; i++) {
int next = b*b + a;
a = b;
b = next % 1000;
}
return b % 1000;
}
Note that this code still won't give you the result for 9223372036854775807 as input. It is simply not possible to loop 9223372036854775807 times. However, this produces the correct result for 100 million in under 5 seconds on my old machine.
The number is to big. It's normal to take so long to process this function.
You can try to check using this:
long startTime = System.currentTimeMillis();
.....your program....
long endTime = System.currentTimeMillis();
long totalTime = endTime - startTime;
System.out.println(totalTime);
the estimate time to finish it.

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.

A program that will solve a log math prob, using Java

I have a programming competition coming up and I am solving last years problems as revision for the competition, i came across a simple program however it requires math which unfortunately i am very bad at.
Here is the question:
Given a positive integer n,find the odd integer o and the
non-negative integer p such that n=o2^p (o multiplied by 2
to the power p)
the first line of the input file contains exactly one positive integer
d equal to the number of test cases,1<=d<=10. the data set follows. Each data set consists of exactly one line containing
exactly one integer n, 1<=n<=10^6
Sample output
2 //d value of number of test cases
24 // value of n
27 // value of n
Sample output
3 3 // first 3 is value of o, 2nd 3 is value of p
7 7 // first 7 is value of o, 2nd 7 is value of p
the "//" part should not be in the output or input
and this is what I have done so far, I got everything right except for the formula I need to use for the equation to solve correctly
public static void main(String[] args) {
double n = 0, d = 0, o = 0, p = 0;
double x = 1;
//START INPUT
Scanner input = new Scanner(System.in);
//input d, number of times program repeats
System.out.println("Please enter the number of times you want to run the test(no more than 10)");
d = input.nextDouble();
//check the validity of d
while((d > 10) || (d<1)){
System.out.println("Invalid input");
System.out.println("Enter another value for d");
d = input.nextDouble();
}
while(x <= d){
x++;
System.out.println("enter a value for n");
n = input.nextDouble();
//check the validity of n
while((n > 1000000) || (n<1)){
System.out.println("Invalid input.");
System.out.println("Enter Another Value for n");
n = input.nextDouble();
}
//Calculates
p = Math.log(n) / Math.log(2.0);
o = n / Math.pow(p, 2);
//STOP CALCULATE
//PRINTS
System.out.println(o + " " + p);
}
}
Any help is appreciated.
All you need to do is repeatedly divide by 2:
function removeTwo(n)
o, p := n, 0
while o % 2 == 0
o, p := o/2, p+1
return o, p
I'll leave it to you to translate to Java.
Many different ways. For programming contests I usually go with a simple approach when there are small numbers: bruteforce! Maybe not a perfect answer to your question, but keep it in mind when doing other tasks at the competition: working is good enough, choose the first solution you can come up with and try implementing it. At least that's true for most competitions I've been at, where it's about doing as many tasks as possible within a given time frame.
For the formula n = o2p,
with o odd and p > 0, and 1 <= n <= 106,
we can see that 2p will always be at least 2.
That means that o should be below half of n, so we only need to search for o's up to half of the value we're given. And we only need to check odd values.
And then one can just try different p values for the chosen o. If the result is higher than n, we should try the next value of o.
javacode:
public void calc(int n) {
for (int o = 1; o <= n / 2; o += 2) {
int p = 1;
while (true) {
int test = o * (int) Math.pow(2, p);
if (test == n) { // solution found
System.out.println("o:" + o + ", p:" + p);
return;
}
if (test > n) break; // total value too high, lets start with another o
p++;
}
}
}
Stepping through this with you input of n=24:
o = 1, p = 1 => 2
o = 1, p = 2 => 4
o = 1, p = 3 => 8
o = 1, p = 4 => 16
o = 1, p = 5 => 32, too high, try another o
o = 3, p = 1 => 6
o = 3, p = 2 => 12
o = 3, p = 3 => 24, TADA!
Different bruteforce methods may be to instead start with the value of p, or to instead divide n by different values of 2p until you get an odd integer.
The problem actually does not involve sooo much math. It's rather about bit twiddling.
It helps to know that each value 2^p is equal to (1<<p). Knowing this, you can first compute the highest bit that is set in n. For example
n = 24 = 11000 (binary) : Highest bit is 4
n = 36 : 100100 (binary) : Highest bit is 5
Then you can start with this bit position as a candiate for p, decrease this value until you find that the equation is solvable. When you reach zero, then the input value n must have been odd. This could be detected explicitly at the beginning, if desired.
import java.util.Arrays;
public class FindFactors
{
public static void main(String[] args)
{
for (int n=0; n<100; n++)
{
System.out.println("For "+n+" : "+Arrays.toString(findFactors(n)));
}
}
private static int[] findFactors(int n)
{
int p = highestBit(n);
while (p >= 0)
{
int twoPowP = (1 << p);
int c = n / twoPowP;
if (c * twoPowP == n)
{
return new int[]{c,p};
}
p--;
}
return null;
}
private static int highestBit(int n)
{
int b = 0;
while (n > 1)
{
n >>= 1;
b++;
}
return b;
}
}

Determining whether a number is a Fibonacci number

I need to to write a Java code that checks whether the user inputed number is in the Fibonacci sequence.
I have no issue writing the Fibonacci sequence to output, but (probably because its late at night) I'm struggling to think of the sequence of "whether" it is a Fibonacci number. I keep starting over and over again. Its really doing my head in.
What I currently have is the nth.
public static void main(String[] args)
{
ConsoleReader console = new ConsoleReader();
System.out.println("Enter the value for your n: ");
int num = (console.readInt());
System.out.println("\nThe largest nth fibonacci: "+fib(num));
System.out.println();
}
static int fib(int n){
int f = 0;
int g = 1;
int largeNum = -1;
for(int i = 0; i < n; i++)
{
if(i == (n-1))
largeNum = f;
System.out.print(f + " ");
f = f + g;
g = f - g;
}
return largeNum;
}
Read the section titled "recognizing fibonacci numbers" on wikipedia.
Alternatively, a positive integer z is a Fibonacci number if and only if one of 5z^2 + 4 or 5z^2 − 4 is a perfect square.[17]
Alternatively, you can keep generating fibonacci numbers until one becomes equal to your number: if it does, then your number is a fibonacci number, if not, the numbers will eventually become bigger than your number, and you can stop. This is pretty inefficient however.
If I understand correctly, what you need to do (instead of writing out the first n Fibonacci numbers) is to determine whether n is a Fibonacci number.
So you should modify your method to keep generating the Fibonacci sequence until you get a number >= n. If it equals, n is a Fibonacci number, otherwise not.
Update: bugged by #Moron's repeated claims about the formula based algorithm being superior in performance to the simple one above, I actually did a benchmark comparison - concretely between Jacopo's solution as generator algorithm and StevenH's last version as formula based algorithm. For reference, here is the exact code:
public static void main(String[] args) {
measureExecutionTimeForGeneratorAlgorithm(1);
measureExecutionTimeForFormulaAlgorithm(1);
measureExecutionTimeForGeneratorAlgorithm(10);
measureExecutionTimeForFormulaAlgorithm(10);
measureExecutionTimeForGeneratorAlgorithm(100);
measureExecutionTimeForFormulaAlgorithm(100);
measureExecutionTimeForGeneratorAlgorithm(1000);
measureExecutionTimeForFormulaAlgorithm(1000);
measureExecutionTimeForGeneratorAlgorithm(10000);
measureExecutionTimeForFormulaAlgorithm(10000);
measureExecutionTimeForGeneratorAlgorithm(100000);
measureExecutionTimeForFormulaAlgorithm(100000);
measureExecutionTimeForGeneratorAlgorithm(1000000);
measureExecutionTimeForFormulaAlgorithm(1000000);
measureExecutionTimeForGeneratorAlgorithm(10000000);
measureExecutionTimeForFormulaAlgorithm(10000000);
measureExecutionTimeForGeneratorAlgorithm(100000000);
measureExecutionTimeForFormulaAlgorithm(100000000);
measureExecutionTimeForGeneratorAlgorithm(1000000000);
measureExecutionTimeForFormulaAlgorithm(1000000000);
measureExecutionTimeForGeneratorAlgorithm(2000000000);
measureExecutionTimeForFormulaAlgorithm(2000000000);
}
static void measureExecutionTimeForGeneratorAlgorithm(int x) {
final int count = 1000000;
final long start = System.nanoTime();
for (int i = 0; i < count; i++) {
isFibByGeneration(x);
}
final double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;
System.out.println("Running generator algorithm " + count + " times for " + x + " took " +elapsedTimeInSec + " seconds");
}
static void measureExecutionTimeForFormulaAlgorithm(int x) {
final int count = 1000000;
final long start = System.nanoTime();
for (int i = 0; i < count; i++) {
isFibByFormula(x);
}
final double elapsedTimeInSec = (System.nanoTime() - start) * 1.0e-9;
System.out.println("Running formula algorithm " + count + " times for " + x + " took " +elapsedTimeInSec + " seconds");
}
static boolean isFibByGeneration(int x) {
int a=0;
int b=1;
int f=1;
while (b < x){
f = a + b;
a = b;
b = f;
}
return x == f;
}
private static boolean isFibByFormula(int num) {
double first = 5 * Math.pow((num), 2) + 4;
double second = 5 * Math.pow((num), 2) - 4;
return isWholeNumber(Math.sqrt(first)) || isWholeNumber(Math.sqrt(second));
}
private static boolean isWholeNumber(double num) {
return num - Math.round(num) == 0;
}
The results surprised even me:
Running generator algorithm 1000000 times for 1 took 0.007173537000000001 seconds
Running formula algorithm 1000000 times for 1 took 0.223365539 seconds
Running generator algorithm 1000000 times for 10 took 0.017330694 seconds
Running formula algorithm 1000000 times for 10 took 0.279445852 seconds
Running generator algorithm 1000000 times for 100 took 0.030283179 seconds
Running formula algorithm 1000000 times for 100 took 0.27773557800000004 seconds
Running generator algorithm 1000000 times for 1000 took 0.041044322 seconds
Running formula algorithm 1000000 times for 1000 took 0.277931134 seconds
Running generator algorithm 1000000 times for 10000 took 0.051103143000000004 seconds
Running formula algorithm 1000000 times for 10000 took 0.276980175 seconds
Running generator algorithm 1000000 times for 100000 took 0.062019335 seconds
Running formula algorithm 1000000 times for 100000 took 0.276227007 seconds
Running generator algorithm 1000000 times for 1000000 took 0.07422898800000001 seconds
Running formula algorithm 1000000 times for 1000000 took 0.275485013 seconds
Running generator algorithm 1000000 times for 10000000 took 0.085803922 seconds
Running formula algorithm 1000000 times for 10000000 took 0.27701090500000003 seconds
Running generator algorithm 1000000 times for 100000000 took 0.09543419600000001 seconds
Running formula algorithm 1000000 times for 100000000 took 0.274908403 seconds
Running generator algorithm 1000000 times for 1000000000 took 0.10683704200000001 seconds
Running formula algorithm 1000000 times for 1000000000 took 0.27524084800000004 seconds
Running generator algorithm 1000000 times for 2000000000 took 0.13019867100000002 seconds
Running formula algorithm 1000000 times for 2000000000 took 0.274846384 seconds
In short, the generator algorithm way outperforms the formula based solution on all positive int values - even close to the maximum int value it is more than twice as fast!
So much for belief based performance optimization ;-)
For the record, modifying the above code to use long variables instead of int, the generator algorithm becomes slower (as expected, since it has to add up long values now), and cutover point where the formula starts to be faster is around 1000000000000L, i.e. 1012.
Update2: As IVlad and Moron noted, I am not quite an expert in floating point calculations :-) based on their suggestions I improved the formula to this:
private static boolean isFibByFormula(long num)
{
double power = (double)num * (double)num;
double first = 5 * power + 4;
double second = 5 * power - 4;
return isWholeNumber(Math.sqrt(first)) || isWholeNumber(Math.sqrt(second));
}
This brought down the cutover point to approx. 108 (for the long version - the generator with int is still faster for all int values). No doubt that replacing the sqrt calls with something like suggested by #Moron would push down the cutover point further.
My (and IVlad's) point was simply that there will always be a cutover point, below which the generator algorithm is faster. So claims about which one performs better have no meaning in general, only in a context.
Instead of passing the index, n, write a function that takes a limit, and get it to generate the Fibonacci numbers up to and including this limit. Get it to return a Boolean depending on whether it hits or skips over the limit, and you can use this to check whether that value is in the sequence.
Since it's homework, a nudge like this is probably all we should be giving you...
Ok. Since people claimed I am just talking thin air ('facts' vs 'guesses') without any data to back it up, I wrote a benchmark of my own.
Not java, but C# code below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SO
{
class Program
{
static void Main(string[] args)
{
AssertIsFibSqrt(100000000);
MeasureSequential(1);
MeasureSqrt(1);
MeasureSequential(10);
MeasureSqrt(10);
MeasureSequential(50);
MeasureSqrt(50);
MeasureSequential(100);
MeasureSqrt(100);
MeasureSequential(100000);
MeasureSqrt(100000);
MeasureSequential(100000000);
MeasureSqrt(100000000);
}
static void MeasureSequential(long n)
{
int count = 1000000;
DateTime start = DateTime.Now;
for (int i = 0; i < count; i++)
{
IsFibSequential(n);
}
DateTime end = DateTime.Now;
TimeSpan duration = end - start;
Console.WriteLine("Sequential for input = " + n +
" : " + duration.Ticks);
}
static void MeasureSqrt(long n)
{
int count = 1000000;
DateTime start = DateTime.Now;
for (int i = 0; i < count; i++)
{
IsFibSqrt(n);
}
DateTime end = DateTime.Now;
TimeSpan duration = end - start;
Console.WriteLine("Sqrt for input = " + n +
" : " + duration.Ticks);
}
static void AssertIsFibSqrt(long x)
{
Dictionary<long, bool> fibs = new Dictionary<long, bool>();
long a = 0;
long b = 1;
long f = 1;
while (b < x)
{
f = a + b;
a = b;
b = f;
fibs[a] = true;
fibs[b] = true;
}
for (long i = 1; i <= x; i++)
{
bool isFib = fibs.ContainsKey(i);
if (isFib && IsFibSqrt(i))
{
continue;
}
if (!isFib && !IsFibSqrt(i))
{
continue;
}
Console.WriteLine("Sqrt Fib test failed for: " + i);
}
}
static bool IsFibSequential(long x)
{
long a = 0;
long b = 1;
long f = 1;
while (b < x)
{
f = a + b;
a = b;
b = f;
}
return x == f;
}
static bool IsFibSqrt(long x)
{
long y = 5 * x * x + 4;
double doubleS = Math.Sqrt(y);
long s = (long)doubleS;
long sqr = s*s;
return (sqr == y || sqr == (y-8));
}
}
}
And here is the output
Sequential for input = 1 : 110011
Sqrt for input = 1 : 670067
Sequential for input = 10 : 560056
Sqrt for input = 10 : 540054
Sequential for input = 50 : 610061
Sqrt for input = 50 : 540054
Sequential for input = 100 : 730073
Sqrt for input = 100 : 540054
Sequential for input = 100000 : 1490149
Sqrt for input = 100000 : 540054
Sequential for input = 100000000 : 2180218
Sqrt for input = 100000000 : 540054
The sqrt method beats the naive method when n=50 itself, perhaps due to the presence of hardware support on my machine. Even if it was 10^8 (like in Peter's test), there are at most 40 fibonacci numbers under that cutoff, which could easily be put in a lookup table and still beat the naive version for the smaller values.
Also, Peter has a bad implementation of the SqrtVersion. He doesn't really need to compute two square roots or compute powers using Math.Pow. He could have atleast tried to make that better before publishing his benchmark results.
Anyway, I will let these facts speak for themselves, instead of the so called 'guesses'.
A positive integer x is a Fibonacci number if and only if one of 5x^2 + 4 and 5x^2 - 4 is a perfect square
There are a number of methods that can be employed to determine if a given number is in the fibonacci sequence, a selection of which can be seen on wikipedia.
Given what you've done already, however, I'd probably use a more brute-force approach, such as the following:
Generate a fibonacci number
If it's less than the target number, generate the next fibonacci and repeat
If it is the target number, then success
If it's bigger than the target number, then failure.
I'd probably use a recursive method, passing in a current n-value (ie. so it calculates the nth fibonacci number) and the target number.
//Program begins
public class isANumberFibonacci {
public static int fibonacci(int seriesLength) {
if (seriesLength == 1 || seriesLength == 2) {
return 1;
} else {
return fibonacci(seriesLength - 1) + fibonacci(seriesLength - 2);
}
}
public static void main(String args[]) {
int number = 4101;
int i = 1;
while (i > 0) {
int fibnumber = fibonacci(i);
if (fibnumber != number) {
if (fibnumber > number) {
System.out.println("Not fib");
break;
} else {
i++;
}
} else {
System.out.println("The number is fibonacci");
break;
}
}
}
}
//Program ends
If my Java is not too rusty...
static bool isFib(int x) {
int a=0;
int b=1;
int f=1;
while (b < x){
f = a + b;
a = b;
b = f;
}
return x == f;
}
Trying to leverage the code you have already written I would propose the following first, as it is the simplest solution (but not the most efficient):
private static void main(string[] args)
{
//This will determnine which numbers between 1 & 100 are in the fibonacci series
//you can swop in code to read from console rather than 'i' being used from the for loop
for (int i = 0; i < 100; i++)
{
bool result = isFib(1);
if (result)
System.out.println(i + " is in the Fib series.");
System.out.println(result);
}
}
private static bool isFib(int num)
{
int counter = 0;
while (true)
{
if (fib(counter) < num)
{
counter++;
continue;
}
if (fib(counter) == num)
{
return true;
}
if (fib(counter) > num)
{
return false;
}
}
}
I would propose a more elegant solution in the generation of fibonacci numbers which leverages recursion like so:
public static long fib(int n)
{
if (n <= 1)
return n;
else
return fib(n-1) + fib(n-2);
}
For the extra credit read: http://en.wikipedia.org/wiki/Fibonacci_number#Recognizing_Fibonacci_numbers
You will see the that there are a few more efficient ways to test if a number is in the Fibonacci series namely: (5z^2 + 4 or 5z^2 − 4) = a perfect square.
//(5z^2 + 4 or 5z^2 − 4) = a perfect square
//perfect square = an integer that is the square of an integer
private static bool isFib(int num)
{
double first = 5 * Math.pow((num), 2) + 4;
double second = 5 * Math.pow((num), 2) - 4;
return isWholeNumber(Math.sqrt(first)) || isWholeNumber(Math.sqrt(second));
}
private static bool isWholeNumber(double num)
{
return num - Math.round(num) == 0;
}
I don't know if there is an actual formula that you can apply to the user input however, you can generate the fibonacci sequence and check it against the user input until it has become smaller than the last number generated.
int userInput = n;
int a = 1, b = 1;
while (a < n) {
if (a == n)
return true;
int next = a + b;
b = a;
a = next;
}
return false;
You can do this in two ways , the recursive and mathematical.
the recursive way
start generating fibonacci sequence until you hit the number or pass it
the mathematical way nicely described here ...
http://www.physicsforums.com/showthread.php?t=252798
good luck.
Consider the sequence of Fibonacci numbers 1,1,2,3,5,8,13,21, etc. It is desired to build 3 stacks each of capacity 10 containing numbers from the above sequences as follows:
Stack 1: First 10 numbers from the sequence.
Stack 2: First 10 prime numbers from the sequence.
Stack 3: First 10 non-prime numbers from the sequence.
(i) Give an algorithm of the flowchart
(ii) Write a program (in BASIC, C++ or Java) to implement this.
Output:As stack operations take place you should display in any convenient form the 3 stacks together with the values held in them.
Finding out whether a number is Fibonacci based on formula:
public static boolean isNumberFromFibonacciSequence(int num){
if (num == 0 || num == 1){
return true;
}
else {
//5n^2 - 4 OR 5n^2 + 4 should be perfect squares
return isPerfectSquare( 5*num*num - 4) || isPerfectSquare(5*num*num - 4);
}
}
private static boolean isPerfectSquare(int num){
double sqrt = Math.sqrt(num);
return sqrt * sqrt == num;
}
Thought it was simple until i had to rack my head on it a few minutes. Its quite different from generating a fibonacci sequence. This function returns 1 if is Fibonnaci or 0 if not
public static int isFibonacci (int n){
int isFib = 0;
int a = 0, b = 0, c = a + b; // set up the initial values
do
{
a = b;
b = c;
c = a + b;
if (c == n)
isFib = 1;
} while (c<=n && isFin == 0)
return isFib;
}
public static void main(String [] args){
System.out.println(isFibonacci(89));
}

Categories

Resources