16

这样做时:

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

这显然是因为结果对于整数来说太大了,但我习惯于为溢出得到大的负数,而不是 0。

提前致谢!


当我切换到这个:

int x = 100;
int result = 1;

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

我明白

4

10 回答 10

26

1到100之间有50个偶数。这意味着阶乘是 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;
}

印刷

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

这意味着 97 位整数对于 fact(100) 的最低位将为 0

事实上,对于 fact(n),2 的幂数非常接近 n。事实上(10000)有 9995 次方 2。这是因为它大约是 1/2 的 n 次幂的总和,总和接近n. 即每第二个数字是偶数n / 2,每4个有一个额外的权力2(+ n / 4),每8个有一个额外的权力(+ n / 8)等接近n总和。

于 2011-03-15T20:51:45.740 回答
21

大负数是溢出到特定范围内的值;factorial(100)最后有超过 32 个二进制零,因此将其转换为整数会产生零。

于 2011-03-15T20:41:19.157 回答
8

要查看原因,我们可以观察阶乘的素因数分解。

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 * ...

的指数2是基数 2 视图中尾随零的数量,因为所有其他因素都是奇数,因此1在最后一个二进制数字中对乘积做出贡献。

类似的方案也适用于其他素数,因此我们可以轻松计算 的因式分解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

因此,如果我们的计算机以 3 为基数存储数字,并且有 48 个三位数字,则为fac(100)0(也为 0 fac(99),但fac(98)不会:-)

于 2011-03-15T21:35:10.700 回答
6

很好的问题 - 答案是:33 的阶乘(由于负值)是-21474836480x80000000或者0xFFFFFFFF80000000如果采用 64 位。乘以 34(下一个成员)将得到一个 long 值0xFFFFFFE600000000,当转换为 int 时会给你0x00000000

显然,从那时起,您将保持 0。

于 2011-03-15T20:47:40.233 回答
3

使用递归和 BigIntegers 的简单解决方案:

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

输出:

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
于 2015-11-22T02:20:43.263 回答
0
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;
    }
    
}   
于 2020-10-13T05:54:54.100 回答
0

(在这里找到,稍微适应了问题)

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);
}
于 2015-07-26T09:02:15.573 回答
0

Java 中的 BigInteger 类。BigInteger 类用于数学运算,涉及非常大的整数计算,超出所有可用原始数据类型的限制。

要计算非常大的数字,我们可以使用BigInteger

比如,如果我们要计算 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);
    }

BigInteger 的主要方法有 BigInteger.ONE、BigInteger.ZERO、BigInteger.TEN、BigInteger.ValueOf()

于 2018-10-03T07:42:00.677 回答
0
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);
    }
}

输出 100 作为输入:

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

输出图像:

输出结果

于 2019-09-09T20:02:18.553 回答
-1

这肯定是溢出,你可以试试双精度,64 位长整数可能太小了

于 2011-03-15T20:45:12.347 回答