My code for whatever reason is printing out a negative number when i run it with certain numbers(17). It is supposed to find the factorial of a number and print it out however clearly that isn't happening.
package recursion;
public class recursion_1 {
public static void main(String[] args) {
int x = factorial(17);
System.out.println(x);
}
public static int factorial(int N) {
if (N == 1) return 1;
return N * factorial(N-1);
}
}
You're encountering integer overflow.
factorial(17) is 3.5568743e+14, which is well beyond the bounds of int. When an integer operation overflows, it can end up negative. For example:
int x = Integer.MAX_VALUE;
x++;
System.out.println(x); // Very large negative number
In your case, you'll have overflowed several times - even if the result were positive, it still wouldn't be right.
If you need integers in the range of [-263, 263-1] you can use long instead of int. If you want arbitrarily large integers, use BigInteger instead. For example:
// Note rename of parameter to follow Java conventions
public static BigInteger factorial(int n) {
return factorial(BigInteger.valueOf(n));
}
public static BigInteger factorial(BigInteger n) {
if (n.equals(BigInteger.ONE)) {
return BigInteger.ONE;
}
return n.multiply(n.subtract(BigInteger.ONE));
}
Factorials grow quickly in value, such that 17! (355687428096000) too large to fit in an int, causing overflow and the negative number.
Return a long from factorial, so that when the multiplication occurs, it won't overflow (yet). You'll need to declare x as a long also. Note that this will only postpone the problem, because sufficiently high values of N will overflow a long too. If necessary, use BigIntegers.
This is because the maximum value an int can have is 2,147,483,647. 17! exceeds this number. If an integer is assigned a number bigger than its maximum size, it starts counting up from -2,147,483,647.
2,147,483,647 + 1 = -12,147,483,647
Try a long or BigDecimal instead =)
Related
I tried to calculate a series of the N first fibonacci numbers using Binets Formula.
Every result i get is correct until F47 where the result is NEGATIVE.
This is my result : -1323752223
And heres the expected result : 2971215073
I really think the problem occures during the double to int conversion
Source Code:
import java.lang.Math;
class fibonacci{
public static int NthFibonacci(int n){
double fi = 1.61803398875;
int fb = (int)Math.round((Math.pow(fi,n) - Math.pow(1-fi,n))/Math.sqrt(5));
return fb;
}
public static void FibonacciSeries(Integer n){
for(int i = 0; i < n; i++){
System.out.println(NthFibonacci(i) + " ");
}
}
public static void main(String[] args) {
FibonacciSeries(50);
}
}
The real explanation for the behavior of the version in your question giving a negative number is a bit subtle.
At F47, this expression
(Math.pow(fi, n) - Math.pow(1 - fi, n)) / Math.sqrt(5)
will give you 2.971215073009069E9 ... which is close to the desired 2971215073.
The problem arises when you call Math.round(2.971215073009069E9). This returns a long - 2971215073L. But then you cast the result of the round call to an int, and it all goes pear-shaped.
Casting a long to an int will just lop off the top 32 bits ... and that results in a meaningless number.
If we modify fibonacci to return a long instead of an int, we get correct results up to F55. F56 and F57 are off by 1. F58 is off by 2.
What is happening now is that we are running into the problem that double (64-bit IEEE floating point) has only about 13.5 decimal digits of precision. The rounding error incurred in the computation of the intermediate floating point value for F56 larger that 0.5 ... so the rounded value is then incorrect.
The computed fibonacci numbers continue to get increasingly inaccurate until you get to F93, where the (modified) fibonacci method returns Long.MAX_VALUE.
To get correct values for very large Fibonacci numbers:
we need to use BigInteger to represent the numbers,
we need to do the computations using BigDecimal with sufficient precision, and (maybe)
we need to use a more accurate value for phi.
Or we need to use the recurrence relationship to compute the numbers.
The 2 take-aways from all of this are:
casting a long to an int is a lossy conversion, and
floating point arithmetic is inexact and ... tricky.
I think that the problem does not have something to do with the double conversion.
int can store numbers that can be represented by 32 bits. This means the highest number integer can represents is 2.147.483.647.
The F47 is breaking this limit and results in an bit-overflow, so it starts at -2.147.483.68 and adds the rest of your 2971215073 - 2147483647 to it. -1323752223 is the outcome.
Use a long (64bit) instead of an int and you should be good :)
2971215073 is too big to be represented as an int at all. The maximum value of an int -- Integer.MAX_VALUE -- is 2^31 - 1, or 2147483647.
Ok so i found a decent fix.
I used a Geometrical version of Binets rule which you can find here : Binets Geometrical Rule
I also used long instead of int so now I can accurately calculate up to F70. F71 is wrong by a digit and after that it just builds up.
New Source Code :
import java.lang.Math;
class fibonacci{
public static long NthFibonacci(int n){
double a = (1/Math.sqrt(5))*Math.pow(2, n);
double radians1 = Math.toRadians(36.0);
double radians2 = Math.toRadians(108.0);
double b = Math.pow(Math.cos(radians1), n) - Math.pow(Math.cos(radians2), n);
long fb = (long) Math.round(a*b);
return fb;
}
public static void FibonacciSeries(int n){
for(int i = 0; i < n; i++){
System.out.println( i + " : " + NthFibonacci(i));
}
}
public static void main(String[] args) {
FibonacciSeries(100);
}
}
i tried using this.
import java.io.*; // for handling input/output
import java.util.*; // contains Collections framework
// don't change the name of this class
// you can add inner classes if needed
class Main {
public static void main (String[] args) {
Scanner s=new Scanner(System.in);
int m=1000000007;
int a=s.nextInt();
int b=s.nextInt();
int c=s.nextInt();
int d=s.nextInt();
long temp1=power(c,d)%m;
long temp2= power(b,temp1)%m;
long result=power(a,temp2)%m;
System.out.println(result);
}
public static long power(int x, long n){
int m=1000000007;
if(n==0){
return 1;
}
if(n==1){
return x;
}
if(n%2==0){
return (power(x,n/2)*power(x,n/2))%m;
}else {
return ((power(x,n/2)*power(x,n/2))%m * x)%m;
}
}
}
but problem is when i increase size of a b c d then its showing TLE.
like for a=2 b=2 c=2 d=2 its giving output 65536 but when i take a=12 b=12 c=12 d=12 output should be 322269119 but using this it is showing Time limit exceed error. anyone can explain how to do this type of qurstion where it said that output value will be large so print is after doing mod 10^9+7.
Edit: a b c d values can be different.
The TLE is due to power recursively calling itself twice per invocation, so it expands to a full binary tree of calls (size: n) instead of into a nice linear chain of calls (length: log(n)) which is how Exponentiation by Squaring is supposed to work. In other words, it's exponentially slower than it needs to be, and for a very boring reason. Easy fix:
public static long power(int x, long n){
int m=1000000007;
if(n==0){
return 1;
}
if(n==1){
return x;
}
long p = power(x,n/2);
if(n%2==0){
return p * p % m;
}else {
return (p * p % m) * x % m;
}
}
But there is also a "math bug" in your program: abcd mod n is not equivalent to a^(b^(c^d mod n) mod n) mod n. Modular addition and multiplication work that way, but exponentiation has a different kind of periodicity.
Just using big integers naively is not sufficient, 12^12^12 would be a 4TB BigInteger, even on a computer that could handle that, computing or using such a physically large number would just take too long. But you can use Euler's theorem, and compute 12^12^12 mod φ(n). 12^12 is no big deal it even fits in a long, then 12 to the power of that long can be a modexp again but modulo φ(1E9+7) which is 1E9+6. For slightly larger c and d, c^d can also be computed as a BigInteger, as long as it isn't too big.
When c or d are so large that c^d is a problem even with BigIntegers, you can use more tricks to compute b^c^d mod φ(n) without the "full" c^d. Unfortunately Euler's theorem is not applicable to the "inner" exponentiation because the GCD of the modulus and the base may not be 1 (and isn't 1 in the example with the twelves), but there is a more complex expression that works in that case.
long iter_cnt = 0;
for (int i = Integer.MAX_VALUE; i <= Integer.MAX_VALUE; i++) {
iter_cnt = iter_cnt + 1;
}
System.out.println(iter_cnt);
I compiled this code and it keeps repeating without stopping. What's wrong with this?
It's happening because Integer.MAX_VALUE + 1 is resetting i to Integer.MIN_VALUE.
public class Main {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE + 1);
System.out.println(Integer.MIN_VALUE);
}
}
Output:
-2147483648
-2147483648
Given below is the explanation from JLS:
If an integer addition overflows, then the result is the low-order
bits of the mathematical sum as represented in some sufficiently large
two's-complement format. If overflow occurs, then the sign of the
result is not the same as the sign of the mathematical sum of the two
operand values.
What happens here is when Integer.MAX_VALUE is added with 1, it sets the minimum value of integer Integer.MIN_VALUE. As we are specifying the datatype as Integer, it can hold maximum upto it's range. When we try to make that value exceeds it's limit, it tends to point the min value of it's datatype. It is same for whatever datatype we specify
I am using the following two functions to calculate factorials and combinations.
public static long Factorial(long n)
{
if (n == 0)
return 1;
else
return n * Factorial(n-1);
}
public static long combinations (long n, long k)
{
return Factorial(n)/(Factorial(k) * Factorial(n - k));
}
I am testing it using:
long test = combinations((long)21, (long)13);
It seems to work for small numbers such as 5,2. But if I try 21,13, I get incorrect answers (negatives or 0).
Would anyone know what is happening here?
The maximum value of long in java is 2^63.
That will safely take you up to the factorial of 20. However, factorial of 21 comes to around 2^65, so you are exceeding the maximum value that can be represented.
See this question for a discussion about what happens in java if you perform a multiplication that results in an overflow.
This is mainly because of overflow from long (64bit signed). You can look up BigDecimal or BigInteger for use in this case.
As other users have said long can't hold Factorial(21). I rewrote your Factorial method using BigInteger and it seems to work, although you have to pass a BigInteger in as the parameter.
public static BigInteger Factorial(BigInteger n)
{
if (n.equals(BigInteger.ZERO))
return BigInteger.ONE;
else
return n.multiply(Factorial(n.subtract(BigInteger.ONE)));
}
Then rewrite your combinations method using BigInteger:
public static BigInteger combinations (BigInteger n, BigInteger k)
{
return Factorial(n).divide(Factorial(k).multiply(Factorial(n.subtract(k))));
}
In the main method I called the combinations method like this
System.out.print(combinations(new BigInteger("21"), new BigInteger("13")));
public static void main(String[]args){
int A[]={2,4,6,9,5,4,5,7,12,15,21,32,45,5,6,7,12};
int multi= 1;
for (int i=0; i<A.length; i++) {
multi *= A[i];
}
System.out.println("The product of the numbers in the array is " + multi );
//I keep getting a negative value but when I shorten the array
//to a few numbers I don't have any problems.
}
That's called overflow.
An integer overflow occurs when an arithmetic operation attempts to create a numeric value that is too large to be represented within the available storage space. [Wikipedia - Integer Overflow]
ints can represent a maximum of (2^32)-1. Your multiplication gives a result that is higher than that value, so it generates overflow.
Change multi type to long and you won't have this problem (but only for that particular case: if you exceed the maximum value representable by a long, you'll have that problem again)
As said, changing the type to long will only postpone the problem, you can solve it by using a BigInteger, which can handle arbitrary-precision integers.
But use it only if you really have to. If you know that your app will do calculations without exceeding the long max representable value, then use a long, as the BigInteger is not a primitive and will be much slower than a long.
Start by declaring multi as a long. When a value exceeds Integer.MAX_VALUE i 'overflows' and becomes negative. The maximum integer value is just more than 2 billion, so it happens quite soon.
You encounter a negative value, it is because the multi value exceeds the Max value of Integer (2^31 -1).
You need to make the change as follows:
From
int multi= 1;
To
long multi= 1;
try this
public static void main(String[]args){
int A[]={2,4,6,9,5,4,5,7,12,15,21,32,45,5,6,7,12};
long multi= 1;
for (int i=0; i<A.length; i++) {
multi *= A[i];
}
System.out.println("The product of the numbers in the array is " + multi );
//I keep getting a negative value but when I shorten the array
//to a few numbers I don't have any problems.
}