my code is displaying wrong output for factorial - java

class TestClass {
public static void main(String args[] ) throws Exception {
long n = 1;
long ans = 1;
Scanner s = new Scanner(System.in);
long N = s.nextInt();
long M = 1000000007;
for (int i=1; i<=N; i++) {
ans = (ans*i) % M;
}
System.out.println(ans);
}
}
for 5! it is giving correct answer but when the value is more i am getting wrong output

Your long M = 1000000007; is buggy. (Is it a throwback to the old C ways of doing this for a narrower type?) Effectively a multiple of 1000000007 will be subtracted to pull a number greater or equal to that back into range: and the result of that will be nonsense.
Don't do that. Rely on Java to wrap-around for you as a last resort.
Then just adopt one of the rules of the long type: since the range of long is fixed in Java, the largest factorial number you can evaluate using that type is also fixed and happens to be 20!:
if (N > 20){
/*an overflow will occur so inform the user of your program*/
}
Do that and drop the M entirely.

Its basically depending on the number M with which you are doing modular operation. try by increasing M like long M = 100000000000007L will generate more valid factorial.

Related

I need to print the 215th Lucas Numbers using an efficient algorithm. Using recursion takes way too long.

The purpose of this class is to calculate the nth number of the Lucas Sequence. I am using data type long because the problems wants me to print the 215th number. The result of the 215th number in the Lucas Sequence is: 855741617674166096212819925691459689505708239. The problem I am getting is that at some points, the result is negative. I do not understand why I am getting a negative number when the calculation is always adding positive numbers. I also have two methods, since the question was to create an efficient algorithm. One of the methods uses recursion but the efficiency is O(2^n) and that is of no use to me when trying to get the 215th number. The other method is using a for loop, which the efficiency is significantly better. If someone can please help me find where the error is, I am not sure if it has anything to do with the data type or if it is something else.
Note: When trying to get the 91st number I get a negative number and when trying to get the 215th number I also get a negative number.
import java.util.Scanner;
public class Problem_3
{
static long lucasNum;
static long firstBefore;
static long secondBefore;
static void findLucasNumber(long n)
{
if(n == 0)
{
lucasNum = 2;
}
if(n == 1)
{
lucasNum = 1;
}
if(n > 1)
{
firstBefore = 1;
secondBefore = 2;
for(int i = 1; i < n; i++)
{
lucasNum = firstBefore + secondBefore;
secondBefore = firstBefore;
firstBefore = lucasNum;
}
}
}
static long recursiveLucasNumber(int n)
{
if(n == 0)
{
return 2;
}
if(n == 1)
{
return 1;
}
return recursiveLucasNumber(n - 1) + recursiveLucasNumber(n - 2);
}
public static void main(String[] args)
{
System.out.println("Which number would you like to know from "
+ "the Lucas Sequence?");
Scanner scan = new Scanner(System.in);
long num = scan.nextInt();
findLucasNumber(num);
System.out.println(lucasNum);
//System.out.println(recursiveLucasNumber(num));
}
}
Two observations:
The answer you are expecting (855741617674166096212819925691459689505708239) is way larger than you can represent using a long. So (obviously) if you attempt to calculate it using long arithmetic you are going to get integer overflow ... and a garbage answer.
Note: this observation applies for any algorithm in which you use a Java integer primitive value to represent the Lucas numbers. You would run into the same errors with recursion ... eventually.
Solution: use BigInteger.
You have implemented iterative and pure recursion approaches. There is a third approach: recursion with memoization. If you apply memorization correctly to the recursive solution, you can calculate LN in O(N) arithmetical operations.
Java data type long can contain only 64-bit numbers in range -9223372036854775808 .. 9223372036854775807. Negative numbers arise due to overflow.
Seems you need BigInteger class for arbitrary-precision integer numbers
I wasn't aware of the lucas numbers before this thread, but from wikipedia it looks like they are related to the fibonacci sequence with (n = nth number, F = fibonacci, L = lucas):
Ln = F_(n-1) + F_(n+1)
Thus, if your algorithm is too slow, you could use the closed form fibonacci and than compute the lucas number from it, alternative you could also use the closed form given in the wikipedia article directly (see https://en.wikipedia.org/wiki/Lucas_number).
Example code:
public static void main(String[] args) {
long n = 4;
double fibo = computeFibo(n);
double fiboAfter = computeFibo(n + 1);
double fiboBefore = computeFibo(n - 1);
System.out.println("fibonacci n:" + Math.round(fibo));
System.out.println("fibonacci: n+1:" + Math.round(fiboAfter));
System.out.println("fibonacci: n-1:" + Math.round(fiboBefore));
System.out.println("lucas:" + (Math.round(fiboAfter) + Math.round(fiboBefore)));
}
private static double computeFibo(long n) {
double phi = (1 + Math.sqrt(5)) / 2.0;
double psi = -1.0 / phi;
return (Math.pow(phi, n) - Math.pow(psi, n)) / Math.sqrt(5);
}
To work around the long size limit you could use java BigDecimal (https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html). This is needed earlier in this approach as the powers in the formula will grow very quickly.

Checking whether a number is in Fibonacci Sequence?

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

Division By Zero Error For Project Euler?

I am trying to solve some project Euler problems and for whatever reason the following code gives me a division by zero error whenever I try to run it with large numbers. Can anyone tell me why?
import java.util.Scanner;
public class Problem3LargestPrimeFactor {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter the number to find the largest prime factor for.");
long num = input.nextLong();
int largest = 1;
boolean isPrime = true;
for(int i = 2; i < num; i++) {
if(num % i == 0) {
for(int u = 2; u < i; u++){
if(i % u == 0)
isPrime = false;
}
if(isPrime)
largest = i;
}
}
}
}
Now I'm aware that this is not the most efficient way to design the algorithm but can anyone tell me what is going on here?
You're overflowing int. In the loop for(int i = 2; i < num; i++), num is a long and i is only an int. When i reaches it's capacity, it wraps around to -2,147,483,648 and keeps being incremented until it gets to 0, at which point you get your error.
Other responses have already pointed out your error. Let me give you a better algorithm for factoring a composite integer using trial division. The basic idea is to simply iterate through the possible factors, reducing n each time you find one. Here's pseudocode:
function factors(n)
f, fs := 2, {}
while f * f <= n
while n % f == 0
append f to fs
n := n / f
f := f + 1
if n > 1
append n to fs
return fs
If you're interested in programming with prime numbers, I modestly recommend this essay at my blog.

ArrayIndexOutOfBounds after solving 'possible loss of precision' compile error

works:meaning no precision error::Just array out of bounds
long a[] =new long[1000000];
int no=2,n;
long i;
a[no]=i+a[n];
if(a[no]>longChain)
{
longChain = a[no];
startNo = no;
}
and when I do
long a[] =new long[1000000];
long no=2,n;
long i,longChain=1,startNo;
a[no]=i+a[n];
if(a[no]>longChain)
{
longChain = a[no];
startNo = no;
}
then loss of precision
found:long
required: int
what is the problem?
My Code for above problem, its ProjectEuler Problem No. 14
class P14
{
public static void main(String args[])
{
long a[] =new long[1000000];
long no=2,n;
long i,longChain=1,startNo;
a[1]=1;
while(no<1000000)
{
n=no;
i=0;
while(n>no-1)
{
if(n%2==0)
n=n/2;
else
n=3*n+1;
i++;
//System.out.println(n);
}
a[no]=i+a[n];
if (a[no] > longChain)
{
longChain=a[no];
startNo=no;
}
no++;
//System.out.println(no);
}
}
}
This is my code for where above problem is occurring
Answer:: Replace a[no] by a[(int)n]
a[n],a[(int)n]
your no and n variables need to be int, not long. Arrays can't be indexed by long. Changing the code to:
int no=2,n;
makes the code compile.
The ArrayIndexOutOfBoundsException is because you wrote the algorithm assuming it was longs.
This code will eventually cause n to become negative:
n=3*n+1;
It's hard to see why when you're doing integer arithmetic. A slight change to make the code use long arithmetic and print the interim result reveals exactly when it becomes negative and how:
while(n>no-1)
{
long newN = n;
if (n % 2 == 0) newN = newN / 2L;
else newN = 3L * newN + 1L;
if (newN > Integer.MAX_VALUE) System.out.println("about to fail");
//this is where the magic happens
n = (int)newN;
System.out.println("converted " + newN + " to " + n);
i++;
}
This is likely because array indexing takes an int as the index. But all your variables are of type long.
a[no]
no is a long.
So using long as an array index is an implicit downcast which could result in loss of precision.
So either you manually cast it down, or you change no to an int.
EDIT: (after additional info in the question)
I'm not 100% sure if this is the cause:
n=3*n+1;
You use n as in index. But n can get pretty large to begin with. So a *3 could make it larger than the size of the array.
You should probably double-check whatever your algorithm is. (which I can't figure out from the code itself)
The problem you have is that you cannot store all the possible values you are calculating in array. Numbers can grow beyond 2^31-1 and you get an overflow.
What you can do is make
long n;
and
while (n > no - 1 || n >= a.length) {
}
// is safe as n < a.length;
a[no] = i + a[(int) n];
This ensures you only look up cached values which are inside your array.
n needs to be long because it may get too large for int. (If you use int it will overflow into negative numbers and cause the ArrayIndexOutOfBoundsException.)
You have to declare n as long and cast it to int when using it as index (no can be int)
a[no]=i+a[(int)n];

Prime factorization algorithm fails for big numbers

I have run into a weird issue for problem 3 of Project Euler. The program works for other numbers that are small, like 13195, but it throws this error when I try to crunch a big number like 600851475143:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at euler3.Euler3.main(Euler3.java:16)
Here's my code:
//Number whose prime factors will be determined
long num = 600851475143L;
//Declaration of variables
ArrayList factorsList = new ArrayList();
ArrayList primeFactorsList = new ArrayList();
//Generates a list of factors
for (int i = 2; i < num; i++)
{
if (num % i == 0)
{
factorsList.add(i);
}
}
//If the integer(s) in the factorsList are divisable by any number between 1
//and the integer itself (non-inclusive), it gets replaced by a zero
for (int i = 0; i < factorsList.size(); i++)
{
for (int j = 2; j < (Integer) factorsList.get(i); j++)
{
if ((Integer) factorsList.get(i) % j == 0)
{
factorsList.set(i, 0);
}
}
}
//Transfers all non-zero numbers into a new list called primeFactorsList
for (int i = 0; i < factorsList.size(); i++)
{
if ((Integer) factorsList.get(i) != 0)
{
primeFactorsList.add(factorsList.get(i));
}
}
Why is it only big numbers that cause this error?
Your code is just using Integer, which is a 32-bit type with a maximum value of 2147483647. It's unsurprising that it's failing when used for numbers much bigger than that. Note that your initial loop uses int as the loop variable, so would actually loop forever if it didn't throw an exception. The value of i will go from the 2147483647 to -2147483648 and continue.
Use BigInteger to handle arbitrarily large values, or Long if you're happy with a limited range but a larger one. (The maximum value of long / Long is 9223372036854775807L.)
However, I doubt that this is really the approach that's expected... it's going to take a long time for big numbers like that.
Not sure if it's the case as I don't know which line is which - but I notice your first loop uses an int.
//Generates a list of factors
for (int i = 2; i < num; i++)
{
if (num % i == 0)
{
factorsList.add(i);
}
}
As num is a long, its possible that num > Integer.MAX_INT and your loop is wrapping around to negative at MAX_INT then looping until 0, giving you a num % 0 operation.
Why does your solution not work?
Well numbers are discrete in hardware. Discrete means thy have a min and max values. Java uses two's complement, to store negative values, so 2147483647+1 == -2147483648. This is because for type int, max value is 2147483647. And doing this is called overflow.
It seems as if you have an overflow bug. Iterable value i first becomes negative, and eventually 0, thus you get java.lang.ArithmeticException: / by zero. If your computer can loop 10 million statements a second, this would take 1h 10min to reproduce, so I leave it as assumption an not a proof.
This is also reason trivially simple statements like a+b can produce bugs.
How to fix it?
package margusmartseppcode.From_1_to_9;
public class Problem_3 {
static long lpf(long nr) {
long max = 0;
for (long i = 2; i <= nr / i; i++)
while (nr % i == 0) {
max = i;
nr = nr / i;
}
return nr > 1 ? nr : max;
}
public static void main(String[] args) {
System.out.println(lpf(600851475143L));
}
}
You might think: "So how does this work?"
Well my tough process went like:
(Dynamical programming approach) If i had list of primes x {2,3,5,7,11,13,17, ...} up to value xi > nr / 2, then finding largest prime factor is trivial:
I start from the largest prime, and start testing if devision reminder with my number is zero, if it is, then that is the answer.
If after looping all the elements, I did not find my answer, my number must be a prime itself.
(Brute force, with filters) I assumed, that
my numbers largest prime factor is small (under 10 million).
if my numbers is a multiple of some number, then I can reduce loop size by that multiple.
I used the second approach here.
Note however, that if my number would be just little off and one of {600851475013, 600851475053, 600851475067, 600851475149, 600851475151}, then my approach assumptions would fail and program would take ridiculously long time to run. If computer could execute 10m statements per second it would take 6.954 days, to find the right answer.
In your brute force approach, just generating a list of factors would take longer - assuming you do not run out of memory before.
Is there a better way?
Sure, in Mathematica you could write it as:
P3[x_] := FactorInteger[x][[-1, 1]]
P3[600851475143]
or just FactorInteger[600851475143], and lookup the largest value.
This works because in Mathematica you have arbitrary size integers. Java also has arbitrary size integer class called BigInteger.
Apart from the BigInteger problem mentioned by Jon Skeet, note the following:
you only need to test factors up to sqrt(num)
each time you find a factor, divide num by that factor, and then test that factor again
there's really no need to use a collection to store the primes in advance
My solution (which was originally written in Perl) would look something like this in Java:
long n = 600851475143L; // the original input
long s = (long)Math.sqrt(n); // no need to test numbers larger than this
long f = 2; // the smallest factor to test
do {
if (n % f == 0) { // check we have a factor
n /= f; // this is our new number to test
s = (long)Math.sqrt(n); // and our range is smaller again
} else { // find next possible divisor
f = (f == 2) ? 3 : f + 2;
}
} while (f < s); // required result is in "n"

Categories