New to Stackoverflow so please point out anything I can do to improve the quality of my question.
So what my code does (or rather hopes to do) is calculate huge fibonacci numbers modulo a pretty huge m. To make the algorithm more efficient, I employ the use of pisano periods. In essence, I calculate the pisano period of m and then make the calculation of the remainder easier by using the following relation:
The remainder of the n th Fibonacci number (modulo m) is equal to the remainder of the k th Fibonacci number (modulo m) such that k = n % p where p is the pisano period of m.
In order to calculate the pisano period, I use the following property:
If the current Fib % m = 0 and the sum of all Fib's until now % m = 0, then the index of the current Fib is the pisano period of m. (Note the index must be greater than 0)
However I run into a problem in this endeavour: To calculate the pisano period, I have to calculate consecutive Fibonacci numbers. The issue arises when the number of Fibonacci numbers that have to be calculate becomes very large, say 100 000. Then the data type long overflows.
To my knowledge, any endeavour to calculate pisano periods will require the calculation of fibonacci's, so the only solution seems to be to replace long with something else. If anyone has any suggestions as to what this replacement might be, I would greatly appreciate it.
import java.util.*;
public class FibHuge {
public static void main (String [] args) {
Scanner in = new Scanner (System.in);
long num = in.nextLong ();
long mod = in.nextLong();
System.out.println ( getMod(num, mod));
}
private static int getMod (long num, long mod) {
Period per = new Period();
long period = per.getPeriod (mod);
int newFibNum = (int)(num % period);
num = (num % mod);
Integer ia[] = new Integer [per.al.size()];
ia = per.al.toArray (ia);
return ia[newFibNum];
}
}
class Period {
ArrayList <Long> al;
long FNum;
long SNum;
Period () {
al = new ArrayList <Long> ();
FNum = 0;
SNum = 1;
}
private long getFib (long first, long second){
return first + second;
}
long getPeriod (long mod){
boolean bool = true;
long fibcount = 0;
long currentmod = 0;
long fib = 0;
long sum = 0;
while (bool){
if (fibcount <= 1){
currentmod = fibcount % mod;
al.add (currentmod);
sum += fibcount;
}
else {
fib = getFib (FNum, SNum);
FNum = SNum;
SNum = fib;
currentmod = (fib % mod);
al.add (currentmod);
sum += fib;
}
if ( (currentmod == 0 & (sum % mod) == 0) & fibcount > 0){
return fibcount;
}
fibcount++;
}
return mod; //essentially just to satisfy the return condition
}
}
Use BigInteger, but take note that it will be much slower, but with infinite size.
You don't need to use BigInteger unless your modulus is too large to fit into a long in which case I suspect you will run out of memory trying to find the solution.
Instead of calculating the n-th Fibonacci number and then performing a modulus, you can calculate the n-th Fibonacci after modulus using this property
(a + b) % n = (a % n + b % n) % n;
In other words you only need to keep adding the modulus of the number in each iteration. You can save all the modulus values in a Set and when you get a repeated result, you have a period. You can store the iteration number with the result and use this to calculate the period.
In fact modulus is kind of expensive but since you will only ever sum a number which is less than 2 * modulus you can simply do
long c = a + b; // Fibonacci
if (c >= modulus) c -= modulus; // the only real change you need for modulus.
As Java uses a condition move rather than an actual branch this is much faster than using %
I can't think of much more details you need to know without writing the code for you.
Related
This is my program, but for really large numbers like 100,000, it works very slowly, is there any option to optimize?
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
BigInteger sum = BigInteger.valueOf(1);
for (BigInteger i = BigInteger.valueOf(n);
i.compareTo(BigInteger.ZERO) > 0;
i = i.subtract(BigInteger.ONE)) {
sum = sum.multiply(i);
}
System.out.println(sum);
}
}
Just to illustrate that it sometimes pays to manipulate the expression, I modified the standard multiplication loop that computes 1*2*3*...*n to break it into two parts: one part multiplies the odd integers together (1*3*5*...) and the other multiplies the evens together (2*4*6*...). The evens product is further broken down by multiplying the evens that are 0 mod 2 but not 0 mod 4 (e.g. 2*6*10*...), then the evens that are 0 mod 4 but not 0 mod 8 (e.g. 4*12*20*28*...) and so on, but the power of 2 is shifted out of the number first. The powers of two are counted up, and the product is then shifted left all at once at the end. This takes advantage of the how the Java 8 BigInteger is implemented to make large left shifts fairly efficient.
private static BigInteger fac4(int n) {
BigInteger evens = multiplyEvens(n);
BigInteger odds = multiplyOdds(n);
BigInteger product = evens.multiply(odds);
return product;
}
private static BigInteger multiplyOdds(int n) {
BigInteger odds = BigInteger.ONE;
for (long i=1; i<=n; i+=2) {
odds = odds.multiply(BigInteger.valueOf(i));
}
return odds;
}
private static BigInteger multiplyEvens(int n) {
BigInteger evens = BigInteger.ONE;
long pow2 = 1;
int shiftAmount = 0;
while ((1 << pow2) <= n) {
for (long i = (1<<pow2); i <= n; i += (1 << (pow2 + 1))) {
shiftAmount += pow2;
evens = evens.multiply(BigInteger.valueOf(i >> pow2));
}
++pow2;
}
return evens.shiftLeft(shiftAmount);
}
public static void main(String[] args) {
// Print out some small factorials to verify things are working
for (int i = 0; i < 10; i++) {
System.out.printf("%d! = %d%n", i, fac4(i));
}
Scanner in = new Scanner(System.in);
int n = in.nextInt();
long start = System.currentTimeMillis();
BigInteger fac = fac4(n);
long end = System.currentTimeMillis();
float total = end - start;
System.out.printf("%d! is %d bits long, took %f seconds to compute", n, fac.bitLength(), total / 1000);
}
Here is the input/output log for one run of n=100000:
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
100000
100000! is 1516705 bits long, took 1.758000 seconds to compute
For comparison, my implementation of the straightforward multiple loop took about 3 seconds.
EDIT:
Here is another implementation I tried that was even faster. The idea is to take advantage of the fact that Java 8+ BigInteger includes asymptotically faster than O(n2) algorithms when the operands of multiply get big enough to provide an advantage. However, the naive method always multiplies a single 'limb' integer by a rapidly growing accumulated product. This approach is not amenable to the faster algorithms. However, if we multiply approximately equal operands then the faster algorithms are possible.
private static final int SIMPLE_THRESHOLD = 10;
private static BigInteger fac6(int n) {
return subfac(1, n);
}
/**
* compute a * (a+1) * ... *(b-1) * b
* The interval [a,b] includes the endpoints a and b.
*
* #param a the interval start.
* #param b the interval end, inclusive.
* #return the product.
*/
private static BigInteger subfac(int a, int b) {
if ((b-a) < SIMPLE_THRESHOLD) {
BigInteger result = BigInteger.ONE;
for (int i=a; i<=b; i++) {
result = result.multiply(BigInteger.valueOf(i));
}
return result;
} else {
int mid = a + (b-a) / 2;
return subfac(a, mid).multiply(subfac(mid+1, b));
}
}
And the output using the same main() method as above was:
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
100000
100000! is 1516705 bits long, took 0.243000 seconds to compute
So fac6() is almost 10 times faster than fac4(). A few experiments suggest that the value of SIMPLE_THRESHOLD has very little effect on the speed, presumably because the overhead of function call is dwarfed by the cost of the BigInteger multiplication.
All these experiments were run on a Mac OS X High Sierra laptop using JDK 1.8.0_181.
This is my first obvious implementation:
public static void main(String[] args) {
long start = System.currentTimeMillis();
int n = 100000;
BigInteger bigInteger = BigInteger.ONE;
for (int i = 1; i < n; i++) {
bigInteger = bigInteger.multiply(BigInteger.valueOf(i));
}
System.out.println(bigInteger);
long end = System.currentTimeMillis();
float total = end - start;
System.out.println(total);
}
Factorial of 100000 is a number with 456569 digits (so I can't print it here), and my solution takes 3.5 seconds, more or less.
If that's not assumible for you, you must design a multi-thread based solution. For instance, one thread multiply first half of n and another thread does the same but for the second half. Then, multiply those two numbers.
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.
I'm writing a small program that displays the factorial of a number.
When I enter the number 20 I got the number 2432902008176640000 as result.
How can I limit a decimal number in Java.
For example the number 2432902008176640000 should be 2432 (limit 4).
Thanks in advance.
The following might do what you want, if what you want to do is what I think you want to do:
long n = 2432902008176640000L; // original number
while (n > 9999) {
// while "more than 4 digits", "throw out last digit"
n = n / 10;
}
// now, n = 2432
And a demo.
Notes:
A long can only represent values as large as 9223372036854775807 (which is only about 4 times as large as the number given) before it will overflow. If dealing with larger numbers you'll need to switch to BigInteger or similar. The same technique can be used, updated for syntax differences.
As fge pointed out, this won't work as it is written over negative numbers; this can be addressed by either changing the condition (i.e. n < -9999) or first obtaining the absolute value of n (and then reverting the operation at the end).
As done in yinqiwen's answer, n > 9999 can be replaced with n >= (long)Math.pow(10, N) (preferably using a temporary variable), where N represents the number of decimal digits.
Replace N by the limit.
long v = 2432902008176640000L;
long x = (long) Math.pow(10, N);
while(v >= x)
{
v /= 10;
}
Try this, may help:
Long n = 2432902008176640000;
String num = String.valueOf(n);
num = num.subString(0, 4);
n = Long.valueOf(num);
I am assuming you mean factorial of a number.
Just convert the number into a string and use substring method to get first 4 digits only.
fact is the factorial value
String result_4_str=(fact+"").substring(0, 4);
long result_4 = Long.parseLong(result_4_str);
System.out.println(result_4);
Some of the previous answers with loops are O(n) time complexity. Here's a solution for constant time complexity:
long num = 2432902008176640000L;
int n = 4;
long first_n = (long) (num / Math.pow(10, Math.floor(Math.log10(num)) - n + 1));
You can try
long number = 2432902008176640000L ;
String numberStr = String.valueOf(number);
if(numberStr.length()>=4){
System.out.println(numberStr.substring(0, 4));
}
I need to work out a very large power modulo (2^32), i.e. I want the result of:
y = (p^n) mod (2^32)
p is a prime number
n is a large integer
Is there a trick to doing this efficiently in Java?
Or am I stuck with doing it in a loop with n iterations?
The simple way to mod 2^32 is to use & 0xFFFFFFFFL. Also, there happens to be a type which naturally keeps the lowest 32-bit called int ;) If you use that you don't even need to perform the & until you have the result (so the answer is unsigned) For this reason you only need to keep the last 32 bit of the answer. To speed up the ^n you can calculate the square, it's square and it's square etc, e.g if n is 0b11111 then you need to multiply p^16 * p^8 * p^4 * p^2 * p.
In short, you can use plain int as you only need 32-bit of accuracy and values with a cost of O(ln n) where n is the power.
int prime = 2106945901;
for (int i = 0; i < 10; i++) {
long start = System.nanoTime();
long answer1 = BigInteger.valueOf(prime)
.modPow(
BigInteger.valueOf(prime),
BigInteger.valueOf(2).pow(32)).longValue();
long mid = System.nanoTime();
int answer2 = 1;
int p = prime;
for (int n = prime; n > 0; n >>>= 1) {
if ((n & 1) != 0)
answer2 *= p;
p *= p;
}
long end = System.nanoTime();
System.out.printf("True answer %,d took %.3f ms, quick answer %,d took %.3f ms%n",
answer1, (mid - start) / 1e6, answer2 & 0xFFFFFFFFL, (end - mid) / 1e6);
}
prints finally
True answer 4,169,684,317 took 0.233 ms, quick answer 4,169,684,317 took 0.002 ms
You can utilize exponentiation by squaring. Firstly, break it down into powers of two for your given n. Since p^n (mod x) == p^(k1) (mod x) . p^(k2) (mod x) . ... p^(kn) (mod x) where sum k_i = n, you can utilize this and successive powers of two to calculate this in O(log n) steps.
In addition to the other answers you can use some elementary number theory to reduce the time needed to compute an mod 232 for a an odd integer to O(1). The Euler Phi function together with Euler's Theorem allows you to discard all but the low-order 31 bits of n.
φ(232) = 231, and aφ(232) = 1 mod 232.
Thus if n = q*(231) + r, 0 <= r < 231, then an mod 232 = ar mod 232
r is simply the low-order 31 bits of n, i.e. n & 0x7fffffff. In fact, by Carmichael's Theorem you can do a bit better (literally), and you only need to consider the low-order 30 bits of n, i.e. n & 0x3fffffff. You can precompute these once and store them in a table of size 4GB for a given base a. Here is some java code as an example.
import java.math.BigInteger;
public class PowMod2_32 {
private static final long MASK32 = 0xffffffffL;
public static long pow32(final int a, final int exponent)
{
int prod = 1;
for (int i = 29; i>=0; i--) {
prod *= prod; // square
if (((exponent >> i) & 1) == 1) {
prod *= a; // multiply
}
}
return prod & MASK32;
}
public static long pow32(BigInteger a, BigInteger exponent) {
return pow32(a.intValue(), exponent.intValue());
}
}
There are no tricks in java that I know of but rather there are some tricks in maths.
If you implement these as an algorithm it should speed up computation.
Look at 5 and 6. Look at 4 also if power of two is always even
Use the Class Bigintiger. here´s an example how to work / pow with it
public String higherPow() {
BigIntiger i = new Bigintger("2");
// doing a power(2^32)
i = i.pow(32);
// after 2^32 was made, do mod 100
i = i.mod(new Bigintiger("100"));
return i.toString();
}
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));
}