ループ継承は最大20までしか計算できませんか?

ループ継承は最大20までしか計算できませんか?

この特別なwhileループは数字20までしか機能しないことを認めます。それ以来、間違った答えが提供され始めましたが、その理由を理解していません。

#!/bin/bash

n=$1
[ "$n" == "" ] && echo Please give a number and try again && exit

factorial=1 ; j=1

while [ $j -le $n ]
do
    factorial=$(( $factorial * $j ))
    j=$(( $j + 1 ))
done
echo The factorial of $n, "$n"'!' = $factorial
exit 0

21を引数として指定すると、-4249290049419214848が得られます。バッシュ問題でしょうか?以下で階乗計算を試しましたが、同じ誤った答えを得ました。答えは次のとおりです。51090942171709440000

echo $(( 2432902008176640000 * 21 ))

答え1

Bashは、ほとんどのシステムで符号付き64ビット整数を使用します。bcこの問題を解決するには、別の同様のツールが必要です。

これは、bashを使用して持つことができる最大数がこの数を超えることを意味し2^63-1ます9,223,372,036,854,775,807

awk 'BEGIN{print 2432902008176640000 * 21}'
51090942171709440000     #--> 51,090,942,171,709,440,000

答え2

doneal24が言ったように去らなければならないかもしれませんbc

Fact.bcというファイルに次の内容を追加します。

define f (x) {
  if (x <= 1) return (1);
  return (f(x-1) * x);
}

これでファイルを提供してbcから呼び出すことができます。

$>bc fact.bc <<< "scale=50;f(200)"
78865786736479050355236321393218506229513597768717326329474253324435\
94499634033429203042840119846239041772121389196388302576427902426371\
05061926624952829931113462857270763317237396988943922445621451664240\
25403329186413122742829485327752424240757390324032125740557956866022\
60319041703240623517008587961789222227896237038973747200000000000000\
00000000000000000000000000000000000

答え3

これを整数オーバーフローエラーと呼びます。@ doneal24の答えによると、Bashは64ビット整数を使用しますが、説明では何が起こっているのかを簡単に示すために8ビット整数を使用します。

8ビット整数は8ビット内に正または負の数を格納しますが、すべてのビットが整数値を格納するわけではありません。数値の最初のビットである符号ビットは、数値が正であるか負であるかを示します。 「0」、負の場合は「1」)、次の7桁は標準のバイナリ表記を使用して関連する数値を形成します。

たとえば、値が1の整数は次のようになります。

0000 0001

その後、プログラムの実行を開始し、次の階乗を計算するために必要な値を掛けて、対応する整数値を増やすことができます。したがって、ここに2を掛けてプロセスを繰り返し始めると、次のような結果が得られます。

0000 0001×0000 0010 = 0000 0010

0000 0010×0000 0011 = 0000 1010

0000 1010×0000 0100 = 0001 1000

0001 1000×0000 0101 = 0111 1000

今、私たちは非常に近づいています。次の反復ではエラーが発生します。

0111 1000×0000 0110 = 0010 1101 0000

整数値を格納するために割り当てられた8ビットがオーバーフローすることがわかります。これは、整数が保存される前にメモリの場所に保存されているすべてを上書きすることを意味し、これはコンピュータプロセスを損傷する可能性があるため、悪いニュースです。過去にも同様のセキュリティ脆弱性を利用してコンピュータを攻撃したことがあります。

ところで、整数位置に格納された8ビットが「1101 0000」であることもわかる。これは、コンピュータがその値を解釈するときに最初のビットを負の数を表す符号ビットとして読み、次に数字の残りの部分を「101 0000」または80として読み取ると、演算の値は「です。-80」。

関連情報