简体   繁体   English

当使用整数用 Java 计算 100 (100!) 的阶乘时,我得到 0

[英]When calculating the factorial of 100 (100!) with Java using integers I get 0

When doing this:这样做时:

int x = 100;
int result = 1;
for (int i = 1; i < (x + 1); i++) {
    result = (result * i);
}
System.out.println(result);

This is clearly because the result is too big for an integer, but I am used to get big negative numbers for the overflow, and not 0.这显然是因为结果对于整数来说太大了,但我习惯于为溢出获得大的负数,而不是 0。

Thanks in advance!提前致谢!


When I switch to this:当我切换到这个时:

int x = 100;
int result = 1;

for (int i = 1; i < (x + 1); i++) {
    result = (result * i);
    System.out.println(result);
}

I get this .我明白

There are 50 even numbers between 1 and 100 inclusive. 1 到 100 之间有 50 个偶数。 This means that the factorial is a multiple of 2 at least 50 times, in other words as a binary number the last 50 bits will be 0. (Actually it is more as even second even number is a multiple of 2*2 etc)这意味着阶乘是 2 的倍数至少 50 次,换句话说,作为二进制数,最后 50 位将为 0。(实际上它更多,因为偶数个偶数是 2*2 的倍数等)

public static void main(String... args) {
    BigInteger fact = fact(100);
    System.out.println("fact(100) = " + fact);
    System.out.println("fact(100).longValue() = " + fact.longValue());
    System.out.println("fact(100).intValue() = " + fact.intValue());
    int powerOfTwoCount = 0;
    BigInteger two = BigInteger.valueOf(2);
    while (fact.compareTo(BigInteger.ZERO) > 0 && fact.mod(two).equals(BigInteger.ZERO)) {
        powerOfTwoCount++;
        fact = fact.divide(two);
    }
    System.out.println("fact(100) powers of two = " + powerOfTwoCount);
}

private static BigInteger fact(long n) {
    BigInteger result = BigInteger.ONE;
    for (long i = 2; i <= n; i++)
        result = result.multiply(BigInteger.valueOf(i));
    return result;
}

prints印刷

fact(100) = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
fact(100).longValue() = 0
fact(100).intValue() = 0
fact(100) powers of two = 97

This means a 97-bit integer would be 0 for the lowest bits of fact(100)这意味着对于 fact(100) 的最低位,97 位整数将为 0

In fact, the number of powers of two is very close to n for fact(n).事实上,对于 fact(n),2 的幂的数量非常接近 n。 For fact(10000) there are 9995 powers of two.事实上 (10000) 有 9995 次 2 的幂。 This is because its is approximately the sum of n times powers of 1/2 giving a total close to n .这是因为它大约是 n 次幂的 1/2 的总和,总和接近n ie every second number is even n/2 and every 4th has an additional power of 2 (+n/4) and every 8th has an additional power (+n/8) etc approaches n as a sum.即每第二个数字是偶数 n/2,每 4 个有 2 的附加幂 (+n/4),每 8 个有一个附加幂 (+n/8) 等接近n作为总和。

Big negative numbers are values that overflowed into certain ranges;大负数是溢出到特定范围内的值; factorial(100) has more than 32 binary zeros on the end, so converting it to an integer produces zero. factorial(100)末尾有超过 32 个二进制零,因此将其转换为整数会产生零。

To have a look at the cause, we could observe the prime factorization of the factorial.要查看原因,我们可以观察阶乘的质因数分解。

fac( 1) = 1             = 2^0
fac( 2) = 2             = 2^1
fac( 3) = 2 * 3         = 2^1 * 3
fac( 4) = 2 * 2 * 2 * 3 = 2^3 * 3
fac( 5) =  ...          = 2^3 * 3 * 5
fac( 6) = ...           = 2^4 * 3^2 * 5
fac( 7) = ...           = 2^4 * ...
fac( 8) = ...           = 2^7 * ...
fac( 9) = ...           = 2^7 * ...
fac(10) = ...           = 2^8 * ...
fac(11) = ...           = 2^8 * ...
...
fac(29) = ...           = 2^25 * ...
fac(30) = ...           = 2^26 * ...
fac(31) = ...           = 2^26 * ...
fac(32) = ...           = 2^31 * ...
fac(33) = ...           = 2^31 * ...
fac(34) = ...           = 2^32 * ...  <===
fac(35) = ...           = 2^32 * ...
fac(36) = ...           = 2^34 * ...
...
fac(95) = ...           = 2^88 * ...
fac(96) = ...           = 2^93 * ...
fac(97) = ...           = 2^93 * ...
fac(98) = ...           = 2^94 * ...
fac(99) = ...           = 2^94 * ...
fac(100)= ...           = 2^96 * ...

The exponent for the 2 is the number of trailing zeros in the base-2 view, as all other factors are odd, and thus contribute a 1 in the last binary digit to the product.对于指数2是在基2视图尾随零的数目,所有其他因素是奇数,从而有助于一个1中的最后一个二进制数位的产物。

A similar scheme works for other prime numbers, too, so we can easily calculate the factorization of fac(100) :类似的方案也适用于其他素数,因此我们可以轻松计算fac(100)的因式分解:

fac(100) = 2^96 * 3^48 * 5^24 * 7^16 * 11^9 * 13^7 * 17^5 * 19^5 * 23^4 *
           29^3 * 31^2 * 37^2 * 41^2 * 43^2 * 47^2 *
           53 * 59 * 61 * 67 * 71 * 73 * 79 * 83 * 89 * 97

So, if our computer stored the numbers in base 3, and had 48-trit-numbers, fac(100) would be 0 (as fac(99) , too, but fac(98) would not :-)因此,如果我们的计算机将数字存储在基数 3 中,并且有 48 个trit-numbers,则fac(100)将是 0(与fac(99) ,但fac(98)不会:-)

Nice problem - answer is: Factorial of 33 (due to negative values) is -2147483648 which is 0x80000000 , or 0xFFFFFFFF80000000 if taking 64bits.好问题 - 答案是:33 的因子(由于负值)是-2147483648 ,即0x80000000 ,如果采用 64 位,则为0xFFFFFFFF80000000 Multiplying by 34 (the next member) will give a long value of 0xFFFFFFE600000000 , which when casting to int will give you 0x00000000 .乘以 34(下一个成员)将给出0xFFFFFFE600000000的 long 值,当转换为 int 时将给出0x00000000

Obviously from that point onwards you will remain with 0.显然,从那时起,您将保持为 0。

Simple solution using recursion and BigIntegers:使用递归和 BigIntegers 的简单解决方案:

    public static BigInteger factorial(int num){
    if (num<=1)
        return BigInteger.ONE;
    else
        return factorial(num-1).multiply(BigInteger.valueOf(num));
    }

Output:输出:

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

(Found here , adapted slightly to fit question) (找到here稍微调整以适应问题)

public static void main(String[] args) {

    BigInteger fact = BigInteger.valueOf(1);
    for (int i = 1; i <= 100; i++)
        fact = fact.multiply(BigInteger.valueOf(i));
    System.out.println(fact);
}

BigInteger Class in Java. Java 中的 BigInteger 类。 BigInteger class is used for mathematical operation which involves very big integer calculations that are outside the limit of all available primitive data types. BigInteger 类用于数学运算,其中涉及超出所有可用原始数据类型限制的非常大的整数计算。

To calculate very large number, we can use BigInteger要计算非常大的数字,我们可以使用BigInteger

Like, If we want to calculate the factorial of 45, answer = 119622220865480194561963161495657715064383733760000000000比如,如果我们要计算 45 的阶乘,答案 = 119622220865480194561963161495657715064383733760000000000

 static void extraLongFactorials(int n) {
       BigInteger fact = BigInteger.ONE;
        for(int i=2; i<=n; i++){
            fact = fact.multiply(BigInteger.valueOf(i));
        }
        System.out.println(fact);
    }

Main methods of BigInteger is BigInteger.ONE, BigInteger.ZERO, BigInteger.TEN, BigInteger.ValueOf() BigInteger 的主要方法是 BigInteger.ONE、BigInteger.ZERO、BigInteger.TEN、BigInteger.ValueOf()

import java.util.*;
import java.math.*;
public class BigInteger_Factorial {
    public static void main(String args []){
        Scanner s = new Scanner(System.in);

        BigInteger x,i,fac = new BigInteger("1");
        x = s.nextBigInteger();

        for(i=new BigInteger("1"); i.compareTo(x)<=0; i=i.add(BigInteger.ONE)){
            fac = fac.multiply((i));
        }
        System.out.println(fac);
    }
}

Output of 100 as input:输出 100 作为输入:

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

Output image:输出图像:

输出结果

package test2;

import java.math.BigInteger;
import java.util.Scanner;

public class Factorial extends Big {

    public static void main(String args []){ 
    int x,fact=1,i ;
    Scanner sc = new Scanner(System.in);
    
    
    System.out.println("press any dight and 0 to exit");
    while (sc.nextInt()!=0)
    {
    System.out.println("Enter the values ");
    x=sc.nextInt();
    if(x<26)

    {
    for( i=1;i<=x;i++)
    {   fact = fact*i;  }
    
    System.out.println("Factorial of "+x + "is "+ fact );
    
    fact=1;
    }
    else 
    {
        System.out.println("In else big....");
    BigInteger k=fact(x);
    
    System.out.println("The factorial of "+x+"is "+k);
    System.out.println("RESULT LENGTH\n"+k.toString().length());
    }
    System.out.println("press any dight and 0 to exit");
    }
    System.out.println("thanks....");
    }
    
        
    
    
}
//----------------------------------------------------//

package test2;

import java.math.BigInteger;

public class Big {

    public static void main(String... args) {
        BigInteger fact = fact(100);
        System.out.println("fact(100) = " + fact);
        System.out.println("fact(100).longValue() = " + fact.longValue());
        System.out.println("fact(100).intValue() = " + fact.intValue());
        int powerOfTwoCount = 0;
        BigInteger two = BigInteger.valueOf(2);
        while (fact.compareTo(BigInteger.ZERO) > 0 && fact.mod(two).equals(BigInteger.ZERO)) {
            powerOfTwoCount++;
            fact = fact.divide(two);
        }
        System.out.println("fact(100) powers of two = " + powerOfTwoCount);
    }

    public static BigInteger fact(long n) {
        BigInteger result = BigInteger.ONE;
        for (long i = 2; i <= n; i++)
            result = result.multiply(BigInteger.valueOf(i));
        return result;
    }
    
}   

肯定是溢出了,你可以试试double,64位长整数可能太小了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM