現在、fortran90を使って階乗を計算するプログラムを作っております。
プログラム内容は、(n !を求めえるプログラム)
n=0
do i=1,100
n=n*i
enddo
このプログラムを実行すると、12!までは予想された値が得られるのですが、13!以降は電卓で計算した値と遙かに異なる値が得られました。
このプログラムは間違っているとは思えないですが、電卓の計算とパソコンの計算が異なる結果になった理由が分かりません。
どなたか、ヒントや参考情報だけでもいいので教えてください。
ちなみにパソコンによる計算結果は、
i n
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
11 39916800
12 479001600
13 1932053504
14 1278945280
15 2004310016
16 2004189184
17 -288522240
18 -898433024
19 109641728
20 -2102132736
21 -1195114496
22 -522715136
23 862453760
24 -775946240
25 2076180480
26 -1853882368
27 1484783616
28 -1375731712
29 -1241513984
30 1409286144
31 738197504
32 -2147483648
33 -2147483648
34 0
35 0
36 0
36の階乗以降0です。
計算結果が正となるが、結果が違うモノ(例えば、13!や31!)は単精度で約10桁程度しか有効数字が得られないためであると思われるのですが、負になったり、0になる理由が分かりません。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
これは、内部的な整数の表現方法の問題です。
まず、この場合、内部的には 32bit 符号付きの整数表現がなされているようです。
たとえば、最小に負の数が出現する
16 2004189184
17 -288522240
を見てみましょう。
これを内部的な16進表示をすると、
16 -> 2004189184 -> 77758000(16) になります。
※16進数で表現すると、8桁分しかないため、こういう数値になっています。
これに、17 を欠けると、16進数では、
7EECD8000 になります。
ここで、実際には、「8桁」しか有効ではありませんから、下位8桁だけが有効になり、
17! は、(7を無視した)EECD8000 になります。
これを、2進数に書き直すと、
EECD8000 = 1110 1110 1010 1011 1000 0000 0000 0000
になって、32bit の一番上位の桁が '1' になっているのがわかります。
ところが、この、「一番上位の桁」は、符号ビットでもあり、ここが、'1' だと、「負の数」だと認識されます。
このため、17! は、負の数だと表示されるわけです。
もうひとつ、この段階でも、下の方の桁は0が並んでいるのに気づいたと思います。
たとえば、普通の10進数で、10を掛ければ、0 が一つ増えます。
10 * 10 = 100, 100 * 10 = 1000
もしも、10進4桁で計算していれば、
1000 * 10 = 10000 ですが、下位4桁しか残りませんから、
1000 * 10 = 0000 = 0 です。
同じように、2進数で、2 を掛ける度に、0がひとつ増えてゆきます。
そこで、32bit だと、2を32回掛けると(たとえば、4 = 2 * 2 なので、4を掛けることは2を2回かけることになるのに注意)
実際には、34 までで偶数が 17個(2を17回)
4の倍数が、34/4 = 8個(つまり、2をさらに、8個掛けることになる)
8の倍数が、34/8 = 4個
16の倍数が、34/16 = 2個
32の倍数が、1 個
存在するため、34! で、2を 17 + 8 + 4 + 2 + 1 = 32個掛けることになるので、34! で、(2進数で表したときに)0 が 32個並ぶことになり、結果的に「0」になります。
それ以降は、0に対するかけ算なので、0のままです。
No.3
- 回答日時:
C で計算、16進表記してみました。
整数32 ビット、負数は2の補数表現な環境です。
10進表記では質問の数値と一致してます。
01 00000001
02 00000002
03 00000006
04 00000018
05 00000078
06 000002d0
07 000013b0
08 00009d80
09 00058980
0a 00375f00
0b 02611500
0c 1c8cfc00
0d 7328cc00
0e 4c3b2800
0f 77775800
10 77758000
11 eecd8000
12 ca730000
13 06890000
14 82b40000
15 b8c40000
16 e0d80000
17 33680000
18 d1c00000
19 7bc00000
1a 91800000
1b 58800000
1c ae000000
1d b6000000
1e 54000000
1f 2c000000
20 80000000
21 80000000
22 00000000
No.1
- 回答日時:
コンピュータは有限の桁しかありません。
整数は2進数を使い、2の補数表現という方法で負の値を使うのがよくある方法です。
nビットの整数だと、2の(n-1)乗-1~ -2の(n-1)乗 まで表現できます。
計算結果が有効な桁を越えた場合は、その越えた分の上の桁が無視されます。
例えば、 4bit整数で最大の 0111(=7)を4倍した場合、 11100(=28)となりますが4桁を越える部分が無視され、 1100 となります。
また、この場合、 1100 は8+4=12ではなく、2の補数表現で負の値 -4 となります。
このあたりは電卓や科学分野、コンピュータでの実数型で使われる「有効数字」とは違います。
有効数字では無視するのは下の桁ですし、正負は別に計算するので変化しません。
出てくる数字を見る限り、32bit符号有り整数での計算をしているようです。
使用できる最大値は2の(n-1)乗-1=2147483647 です。
13! = 6706022400 = 17328cc00(16)
であり、すでに33bit目があるので、32bitに削られ
7328cc00(16) = 1932053504(10)
となっています。
また、 33!までは、素因数分解すると、2が31個以下なので2の31乗以内の桁に0で無い値がありますが、34!以降は2が32個以上になるので、最低でも2の32乗になり、32bitの範囲には0しか無いことになります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
FORTRANでの階乗の表現
その他(プログラミング・Web制作)
-
シグマの計算をプログラムで
その他(教育・科学・学問)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
c languageで 簡単な質問があ...
-
O(n log n)について2
-
時刻の比較
-
三菱シーケンサ(Aシリーズ)で...
-
ExcelでPC(パソコン)によって...
-
”/”を使わずに割り算したいんで...
-
8進数と16進数表現について
-
floatの有効桁数
-
16進数 加算 減算 C言語
-
VB.net Double と...
-
色の判定
-
Excel 計算結果誤差
-
MS-VisualStudio 2003と2005(マ...
-
大きすぎる数値になるとE+にな...
-
2進数、16進数、10進数のことを...
-
ExcelのINT関数の計算結果がお...
-
BCD・HEX・BINについて
-
powf を使わずにべき乗を計算
-
C言語のfloat型変数の値代入と...
-
逆ポーランド記法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
c languageで 簡単な質問があ...
-
ExcelでPC(パソコン)によって...
-
16進数 加算 減算 C言語
-
ExcelのINT関数の計算結果がお...
-
EXCELの関数"STDEV(標準偏差)"...
-
三菱シーケンサ(Aシリーズ)で...
-
VB.net Double と...
-
除算を使わずに10で割りたい。
-
有効数字について 以前質問をし...
-
BCD・HEX・BINについて
-
C言語でセルオートマトンを作成...
-
VB6.0での小数点の扱いについて
-
VBAでミリ秒まで出力する方法
-
2進数の足し算(C言語)
-
”/”を使わずに割り算したいんで...
-
floatの有効桁数
-
計算の丸め誤差の解消について
-
VB6のFIX関数での誤差について
-
三角比の俯角の計算
おすすめ情報