[英]When calculating the factorial of 100 (100!) with Java using integers I get 0
這樣做時:
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);
}
我明白了。
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
這意味着對於 fact(100) 的最低位,97 位整數將為 0
事實上,對於 fact(n),2 的冪的數量非常接近 n。 事實上 (10000) 有 9995 次 2 的冪。 這是因為它大約是 n 次冪的 1/2 的總和,總和接近n
。 即每第二個數字是偶數 n/2,每 4 個有 2 的附加冪 (+n/4),每 8 個有一個附加冪 (+n/8) 等接近n
作為總和。
大負數是溢出到特定范圍內的值; factorial(100)
末尾有超過 32 個二進制零,因此將其轉換為整數會產生零。
要查看原因,我們可以觀察階乘的質因數分解。
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 個trit-numbers,則fac(100)
將是 0(與fac(99)
,但fac(98)
不會:-)
好問題 - 答案是:33 的因子(由於負值)是-2147483648
,即0x80000000
,如果采用 64 位,則為0xFFFFFFFF80000000
。 乘以 34(下一個成員)將給出0xFFFFFFE600000000
的 long 值,當轉換為 int 時將給出0x00000000
。
顯然,從那時起,您將保持為 0。
使用遞歸和 BigIntegers 的簡單解決方案:
public static BigInteger factorial(int num){
if (num<=1)
return BigInteger.ONE;
else
return factorial(num-1).multiply(BigInteger.valueOf(num));
}
輸出:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
(找到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);
}
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()
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
輸出圖像:
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.