Why does my factorial program print 0? - java

This code is meant to find 100 factorial and the sum the digits in the number. However, it returns 0.
Why does this happen?
public class Problem20 {
public static void main(String[] args){
int num = 100;
for(int i = 1; i< 100; i++){
num = num * i;
}
String numstring = Integer.toString(num);
int sum = 0;
for(int j = 0; j < numstring.length(); j++){
sum += numstring.charAt(j) - '0';
}
System.out.print(sum);
}
}

Every time you multiply by 2, you add a 0 to the low bits of binary representation of the number.
According to the JLS §15.17.1:
If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format. As a result, if overflow occurs, then the sign of the result may not be the same as the sign of the mathematical product of the two operand values.
Here's some code to demonstrate this point. As you can see, the number of 0 at the end of the number slowly increases; soon as we get to 32, the low order bits become all 0. See: Why does this multiplication integer overflow result in zero?
public class Problem20 {
public static void main(String[] args) {
int num = 100;
for (int i = 1; i < 33; i++) {
num = num * i;
System.out.println(i + "\t" + Integer.toBinaryString(num));
}
}
}
Output:
1 1100100
2 11001000
3 1001011000
4 100101100000
5 10111011100000
6 10001100101000000
7 1111011000011000000
8 1111011000011000000000
9 10001010011011011000000000
10 10101101000010001110000000000
11 11101101111011000011010000000000
12 100111000100100111000000000000
13 11111011111011111011000000000000
14 11000111000110111010000000000000
15 10101010100111100110000000000000
16 10101001111001100000000000000000
17 1001000010001100000000000000000
18 10100111011000000000000000000
19 10001101100001000000000000000000
20 1110010100000000000000000000
21 101100100100000000000000000000
22 11010100011000000000000000000000
23 10100101000000000000000000000
24 11101111000000000000000000000000
25 1010111000000000000000000000000
26 11010110000000000000000000000000
27 10010010000000000000000000000000
28 11111000000000000000000000000000
29 11000000000000000000000000000
30 11010000000000000000000000000000
31 110000000000000000000000000000
32 0
You can solve this problem by using BigInteger instead of int, e.g.
import java.math.BigInteger;
public class Problem20 {
public static void main(String[] args) {
BigInteger num = BigInteger.valueOf(100);
for (int i = 1; i < 100; i++) {
num = num.multiply(BigInteger.valueOf(i));
System.out.println(num);
}
}
}

Alright.
1! = 1
2! = 2
3! = 6
4! = 24
.
.
.
10! = 3628800
.
.
100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Do you think this fits in any of those data-types?
What happens once a number crosses the limit? It overflows. And hence you get a wrong answer.
So what do I do?
Use BigInteger.

Related

Why is this code printing a negative number?

public class Program {
public static void main(String[] args) {
int x = 1;
for (int i = 1; i < 31; i++) {
x = x + 2 * x;
}
System.out.println(x);
}
}
It prints -1010140999 and I don't know why it is negative number.
Final output is a very long number which will exceed the max integer capaxity. Hence we need to use long data type. Please check the correct code below with x value at each iteration
public class Program {
public static void main(String[] args) {
long x = 1;
for (int i = 1; i < 31; i++) {
x = x + 2l * x;
System.out.println(i+ " " +x);
}
}
}
Output
1 3
2 9
3 27
4 81
5 243
6 729
7 2187
8 6561
9 19683
10 59049
11 177147
12 531441
13 1594323
14 4782969
15 14348907
16 43046721
17 129140163
18 387420489
19 1162261467
20 3486784401
21 10460353203
22 31381059609
23 94143178827
24 282429536481
25 847288609443
26 2541865828329
27 7625597484987
28 22876792454961
29 68630377364883
30 205891132094649
An integer in Java is stored with 32 bits, of which one is used to indicate whether the value is positive or negative. This means an int's value is between -2^31 and 2ˆ31 - 1.
Once you add or subtract past those limits, you wrap around in the corresponding direction since an overflow/underflow occurs.
public class OverflowExample {
public static void main(String args[]) {
int largest_int = Integer.MAX_VALUE;
int smallest_int = Integer.MIN_VALUE;
System.out.println(largest_int); // 2ˆ31 - 1 = 2147483647
System.out.println(largest_int + 1); // -2147483648
System.out.println(smallest_int); // -2^31, same as above
}
}

Strange bug with Catalan number generator

I'm trying to write a iterative catalan number generator as opposed to a recursive one. It works, but only up until the number "10", and then it starts to print out numbers that don't make sense. Here's what I have so far.
public static long dpr1(int n)
{
long [] Array = new long[(2*n)+1];
Array[0]=1;
Array[1]=1;
int count=0;
long c=0;
for(int i = 2; i<=(2*n); i++){
Array[i]=(i)*(Array[i-1]);
count=i;
}
return(((Array[count])/(((Array[n]))*(Array[n])))/(n+1));
}
I've been testing it using this as a main:
public class CatalanTest
{
public static void main(String[] args)
{
long startTime, endTime, result;
for (int n = 2; n < 18; n = n + 2)
{
System.out.println(Catalan.dpr1(n));
}}}
Which returns
2
14
132
1430
16796
-2
97
0
Which are the corresponding Catalan numbers for the even numbers between 2 and 10, but after that the values don't make a ton of sense and I have no idea why. Any help sorting this out would be appreciated.
Based on this code A[i] is equal to Factorial(i). When n=11, you calculate Factorial up to 22, and Factorial(22) is larger than the max value of long, so your calculations overflow, and the result is wrong.
You can avoid the overflow is you realize that:
(Array[count] / (Array[n]*Array[n])) / (n+1) =
((2*n)!/(n!*n!))/(n+1) =
((n+1)*(n+2)*...*(2n)/(n!))/(n+1)=
(n+2)*(n+3)*...*(2n)/(n!)
So you can forget about your array and just calculate this formula, which would work without overflowing for larger values of n.
Your entire code can be reduced to :
for (long n=2;n<18;n+=2) {
long res = 1;
for (long l=n+2;l<=2*n;l++)
res *= l;
for (long l=2;l<=n;l++)
res=res/l;
System.out.println(res);
}
Which produces this output (it looks like we still get an overflow for n=16):
2
14
132
1430
16796
208012
2674440
91351
To avoid that, we can combine the multiplications and divisions, in order to keep the intermediate result small :
for (long n=2;n<18;n+=2) {
double res = 1;
for (long l=n+2;l<=2*n;l++) {
res *= l;
res /= (l-n);
}
System.out.println((long)res);
}
This produces :
2
14
132
1430
16796
208012
2674440
35357670

Project-Euler -- Problem20

I thought I solved this problem but the program output "0". I don't see any problem. Thank you for helping.
Question :
n! means n × (n − 1) × ... × 3 × 2 × 1
For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, and the sum of
the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.
Find the sum of the digits in the number 100!
package projecteuler;
public class problem20 {
public static void main(String[] args)
{
int sayi=0;
int carpim=1;
for(int i=100;i>=1;i--)
{
carpim*=i;
}
String carp=""+carpim;
int[] dizi = new int[carp.length()];
String[] dizis=new String[carp.length()];
for(int i=0;i<carp.length();i++)
{
dizis[i]=carp.substring(i);
}
for(int i=0;i<carp.length();i++)
{
dizi[i]=Integer.parseInt(dizis[i]);
sayi+=dizi[i];
}
System.out.println(sayi);
}
}
100! is 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
, and that exceeds the valid range of an int (by rather a lot). Try using a BigInteger. To get you started,
BigInteger carpim = BigInteger.ONE;
for (int i = 100; i >= 1; i--) {
carpim = carpim.multiply(BigInteger.valueOf(i));
}
System.out.println(carpim);
The output of which is the number mentioned before.
It appears the number is overflowing. https://ideone.com/UkXQ4e
4611686018427387904
-4611686018427387904
-9223372036854775808
-9223372036854775808
0
0
0
You might want to try a different class for the factorial like BigInteger
In college, I got this example for finding n! using this algorithm. this is based on the fact that n! = n * (n-1)! (for example, 5! = 4 * 3!). Using a recursive algorithm:
function factorial(n)
if (n = 0) return 1
while (n != 0)
return n * [factorial(n-1)]
once you have 100!, its easy to parse it as String and make Integers out of it to get the sum
int sum = 0;
for (Character c : yourBigInteger.toString().toCharArray()) {
sum = sum + Integer.parseInt(c.toString());
}
System.out.println(sum);
public static void descomposicionFactorial(int num) {
BigInteger factorial = BigInteger.ONE;
for (int i = num; i > 0; i--) {
factorial = factorial.multiply(BigInteger.valueOf(i));
}
String aux =factorial.toString();
char cantidad[] = aux.toCharArray();
int suma = 0, numero = 0;
for (int i = 0; i <cantidad.length; i++) {
numero = cantidad[i] - '0';
suma += numero;
}
System.out.println(suma);
}

Competitive Programing: Factorial Time limit exceeded

I am working on a very simple spoj problem in which we have to take input N calculate its factorial then find out number of trailing zeros and display it some thing like
Sample Input:
6
3
60 // fact of 60 has 14 trailing zeros
100
1024
23456
8735373
Sample Output:
0
14
24
253
5861
2183837
so i have written a code which is working fine on my machine but when i am submitting it is giving me time limit error. i don't know how to make this code fast. So i want suggestions from you guys.
public class Factorial {
public static void main(String[] args) throws IOException {
try {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(bf.readLine());
for (int i = 0; i < t; i++) {
Long num = Long.parseLong(bf.readLine());
BigInteger bd = BigInteger.valueOf(num);
System.out.println(countTrailinZeros(factorial(bd.toString())));
}
} catch (IllegalStateException e) {
return;
}
}
public static BigInteger factorial(String n) {
BigInteger x = BigInteger.valueOf(1);
for (long i = 1; i <= Integer.parseInt(n); i++) {
x = x.multiply(BigInteger.valueOf(i));
}
return x;
}
public static int countTrailinZeros(BigInteger bd) {
String s = bd.toString();
int glen = s.length();
s = s.replaceAll("[0.]*$", "");
int llen = s.length();
return glen - llen;
}
}
I have googled about some possible solutions and found out that lookup table may work i don't have much idea about this. I'd be very thankful if some can explain me about lookup table.
edit: Could it be java is too slow to solve this problem in given time? or in general it is not favorable to use java for competitive programing?
you dont need to calculate factorial to get number of trailing zeroes.
Solution :
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int lines = Integer.parseInt(br.readLine());
int sum, N, p;
for (int i = 0; i < lines; i++) {
N = Integer.parseInt(br.readLine());
sum = 0;
p = 5;
while (N / p != 0) {
sum = sum + N / p;
p = p * 5;
}
System.out.println(sum);
}
}
}
Logic is :
The highest power of a prime number p in N! is given by
floor(N/p) + floor(N/p*p) + floor(N/p*p*p) ... so on till [floor(N/p^n) = 0]
so since number of ending zeroes is required , ans = min(max power of 2 in N!, max power of 5 in N!)
because zeroes appears on multiplication by ten and ten can be decomposed to 10 = (2 * 5).
It is fine to assume that max power of 5 in N! is always less than max power of 2 in N!.
as multiples of 2 occur more frequently than multiples of 5.
So problem reduces to finding max power of 5 in N! and hence the solution.
Example :
N = 5
max power of 5 in 5! = floor(5/5) + floor(5/25) => 1 + 0 => ans = 1
N = 100
max power of 5 in 100! = floor(100/5) + floor(100/25) + floor(100/125) => 20 + 4 + 0 => ans = 24
I have solved the same problem in spoj platform, you just have to divide the value by 5 until the value becomes less than 5. print all the result of the division and that's your output.
To solve this problem, consider prime factorization of N factorial:
N! = 2^a1 * 3^a2 * 5^a3 * .... where a1, a2, a3, ... >= 0
Since N! = N*(N-1)(N-2)..., multiples of 2 are more frequent than 5.
So, a1 >= a3 in this expansion.
Number of trailing zeros = how many times you can divide N! by 10.
Which implies, ans = min(a1, a3) based on the prime factorization given above.
Since we already proved a1 >= a3, hence ans = a3, i.e power of 5 in the prime factorization of N!.
There will be floor(N/5) numbers that will contribute to power of 5 atleast once.
There will be floor(N/25) numbers that will contribute to power of 5 atleast twice.
There will be floor(N/125) numbers that will contribute atleast thrice
and so on.
The total power of 5 = floor(N/5) + floor(N/25) + floor(N/125) + ...
Implementation of this formula in code is left as an exercise.

Why the output result of this value is always zero?

I'm running this code, but why the output result of m is always zero here?
This is very strange since m is initialized to 2.
public class ScalabilityTest {
public static void main(String[] args) {
long oldTime = System.currentTimeMillis();
double[] array = new double[100000];
int p = 2;
int m = 2;
for ( int i = 0; i < array.length; i++ ) {
p += p * 12348;
for ( int j = 0; j < i; j++ ) {
double x = array[j] + array[i];
m += m * 12381923;
}
}
System.out.println( (System.currentTimeMillis()-oldTime) / 1000 );
System.out.println( p + ", " + m );
}
}
Since you are always multiplying the value of m with a number and add to m, on the 16th iteration it overflows to become 0.
In fact, since you are multiplying the number with an odd number then add it to the original, you are multiplying it with a even number, which make the trailing 0 bits moves at least one step left, thus it ends with 0:
1 1011110011101110111001000 24763848
2 1111011100110010111011000100000 2073654816
3 1111111111111101111010010000000 2147415168
4 10010100011000001100001000000000 -1805598208
5 10010010100010001100100000000000 -1836529664
6 10001011110000100010000000000000 -1950212096
7 1110010101001001000000000000000 1923383296
8 1001100000100000000000000000 159514624
9 1010011110010000000000000000000 1405616128
10 10001110001000000000000000000000 -1910505472
11 1010100100000000000000000000000 1417674752
12 1000010000000000000000000000000 1107296256
13 11001000000000000000000000000000 -939524096
14 100000000000000000000000000000 536870912
15 10000000000000000000000000000000 -2147483648
16 0 0
Here's an observation: as soon as m reaches 0, executing
m += m * 12381923;
Will keep m at 0.
I wrote a program to output the values of m as it goes, and here's what I found:
2
24763848
2073654816
2147415168
-1805598208
-1836529664
-1950212096
1923383296
159514624
1405616128
-1910505472
1417674752
1107296256
-939524096
536870912
-2147483648
0
Converged after 16 iterations.
For reference, here's the source:
public class Converge {
public static void main(String[] args) {
int m = 2;
long counter = 0; // Unnecessary, but I didn't know how many iterations we'd need!
while (m != 0) {
System.out.println(m);
m += m * 12381923;
counter++;
}
System.out.println(m);
System.out.println("Converged after " + counter + " iterations.");
}
}
Hope this helps!
It is because the int value overflows. The following documentation shows that the maximum value of an int is 2,147,483,647 and by the time the sixteenth iteration occurs, m is greater than this value and hence it overflows.

Categories