2017-04-12 9 views
3

私は、2つの単純なサイクルを使用して最初の数の自然数の階乗を計算するコンパイルされた言語で簡単なプログラムを実行しました。 1から数の自然数を掛けて階乗を計算します。 プログラムは最初の自然数に対しては完全に機能し、その後はおよそ13番目の値から計算された階乗は明らかに間違っています。これは現代のコンピュータで実装されている整数演算によるもので、負の値が発生するのはなぜかわかりません。 なぜ私は分かりませんが、これは私が別のコンピュータでテストしたものです。もちろん、n階階乗が0と評価された場合、(n + 1)階階乗も0と評価されますが、なぜ数0は常に非常に少数の階乗計算?Factorialループが0になる

EDIT:なぜ私は1つではなく2つの異なるサイクルを使用したのか疑問に思うかもしれません...私はコンピュータが最初からすべての階乗を再計算するように強制しました。 0であり、偶然ではありません。

はここに私の出力です:

Output of my program

+0

"コンパイルされた言語" ...意味?あなたは用語を知っているようですが、あなたの "現代のコンピュータ"は依然として整数のオーバーフローを受けています –

+1

あなたのコードを示してください。 – Mazz

答えて

7

34からスタート!、すべての階乗は2^32で割り切れるです。だから、あなたのコンピュータプログラムが2^32のモジュロを計算すると(使用しているプログラミング言語は何も言っていませんが、これはそうです)、結果は常に0になります。

Pythonで2^32の階乗はMOD計算:

def sint(r): 
    r %= (1 << 32) 
    return r if r < (1 << 31) else r - (1 << 32) 

r = 1 
for i in xrange(1, 40): 
    r *= i 
    print '%d! = %d mod 2^32' % (i, sint(r)) 

独自のプログラムからの出力と一致し、この出力を、与える:

1! = 1 mod 2^32 
2! = 2 mod 2^32 
3! = 6 mod 2^32 
4! = 24 mod 2^32 
5! = 120 mod 2^32 
6! = 720 mod 2^32 
7! = 5040 mod 2^32 
8! = 40320 mod 2^32 
9! = 362880 mod 2^32 
10! = 3628800 mod 2^32 
11! = 39916800 mod 2^32 
12! = 479001600 mod 2^32 
13! = 1932053504 mod 2^32 
14! = 1278945280 mod 2^32 
15! = 2004310016 mod 2^32 
16! = 2004189184 mod 2^32 
17! = -288522240 mod 2^32 
18! = -898433024 mod 2^32 
19! = 109641728 mod 2^32 
20! = -2102132736 mod 2^32 
21! = -1195114496 mod 2^32 
22! = -522715136 mod 2^32 
23! = 862453760 mod 2^32 
24! = -775946240 mod 2^32 
25! = 2076180480 mod 2^32 
26! = -1853882368 mod 2^32 
27! = 1484783616 mod 2^32 
28! = -1375731712 mod 2^32 
29! = -1241513984 mod 2^32 
30! = 1409286144 mod 2^32 
31! = 738197504 mod 2^32 
32! = -2147483648 mod 2^32 
33! = -2147483648 mod 2^32 
34! = 0 mod 2^32 
35! = 0 mod 2^32 
36! = 0 mod 2^32 
37! = 0 mod 2^32 
38! = 0 mod 2^32 
39! = 0 mod 2^32 

そして、ここでは、この範囲の正確な値のテーブルです2のそれぞれにどれくらいの力があるのか​​を示す階乗:

1! = 1. Divisible by 2^0 
2! = 2. Divisible by 2^1 
3! = 6. Divisible by 2^1 
4! = 24. Divisible by 2^3 
5! = 120. Divisible by 2^3 
6! = 720. Divisible by 2^4 
7! = 5040. Divisible by 2^4 
8! = 40320. Divisible by 2^7 
9! = 362880. Divisible by 2^7 
10! = 3628800. Divisible by 2^8 
11! = 39916800. Divisible by 2^8 
12! = 479001600. Divisible by 2^10 
13! = 6227020800. Divisible by 2^10 
14! = 87178291200. Divisible by 2^11 
15! = 1307674368000. Divisible by 2^11 
16! = 20922789888000. Divisible by 2^15 
17! = 355687428096000. Divisible by 2^15 
18! = 6402373705728000. Divisible by 2^16 
19! = 121645100408832000. Divisible by 2^16 
20! = 2432902008176640000. Divisible by 2^18 
21! = 51090942171709440000. Divisible by 2^18 
22! = 1124000727777607680000. Divisible by 2^19 
23! = 25852016738884976640000. Divisible by 2^19 
24! = 620448401733239439360000. Divisible by 2^22 
25! = 15511210043330985984000000. Divisible by 2^22 
26! = 403291461126605635584000000. Divisible by 2^23 
27! = 10888869450418352160768000000. Divisible by 2^23 
28! = 304888344611713860501504000000. Divisible by 2^25 
29! = 8841761993739701954543616000000. Divisible by 2^25 
30! = 265252859812191058636308480000000. Divisible by 2^26 
31! = 8222838654177922817725562880000000. Divisible by 2^26 
32! = 263130836933693530167218012160000000. Divisible by 2^31 
33! = 8683317618811886495518194401280000000. Divisible by 2^31 
34! = 295232799039604140847618609643520000000. Divisible by 2^32 
35! = 10333147966386144929666651337523200000000. Divisible by 2^32 
36! = 371993326789901217467999448150835200000000. Divisible by 2^34 
37! = 13763753091226345046315979581580902400000000. Divisible by 2^34 
38! = 523022617466601111760007224100074291200000000. Divisible by 2^35 
39! = 20397882081197443358640281739902897356800000000. Divisible by 2^35 
+0

私は前にその事実を聞いていなかった。あなたは証拠へのリンクを持っていますか? – paddy

+1

@paddyあなたは2の係数を数えることができます。1 ... 34では、2で割り切れる床(34/2)数、4で割り切れる床(34/4)数、4で割り切れる床(34/8) 8、など。 「(34 // 2)+(34 // 4)+(34 // 8)+(34 // 16)+(34 // 32)= 32」となる。 –

+0

整数の符号(+または - )に1ビットが使用されていませんか?それでは、2^31で割り切れる数はいつも0になっていませんか? – John

2

各乗算は、いくつかの反復で左端のビットが原因のオーバーフロー廃棄されるまで右からゼロのビットを付加します。アクションで 効果:

int i, x=1; 
    for (i=1; i <=50; i++) { 
     x *= i; 
     for (int i = 31; i >= 0; --i) { 
      printf("%i",(x >> i) & 1); 
     } 
     printf("\n"); 
    } 

出力ビット:我々はゼロを取得する前にすることを

 
00000000000000000000000000000001 
00000000000000000000000000000010 
00000000000000000000000000000110 
00000000000000000000000000011000 
00000000000000000000000001111000 
00000000000000000000001011010000 
00000000000000000001001110110000 
00000000000000001001110110000000 
00000000000001011000100110000000 
00000000001101110101111100000000 
00000010011000010001010100000000 
00011100100011001111110000000000 
01110011001010001100110000000000 
01001100001110110010100000000000 
01110111011101110101100000000000 
01110111011101011000000000000000 
11101110110011011000000000000000 
11001010011100110000000000000000 
00000110100010010000000000000000 
10000010101101000000000000000000 
10111000110001000000000000000000 
11100000110110000000000000000000 
00110011100000000000000000000000 
11010000000000000000000000000000 
10000000000000000000000000000000 
00000000000000000000000000000000 

はお知らせ - 私たちはINT_MINを取得します。さらにもう1つのゼロビットを追加すると、符号ビットが破棄され、INT_MINからプレーンゼロが得られます。

+0

素敵な視覚化! –

関連する問題