私のスクリプトがそれ自体の最大数を決定できるようにするにはどうすればよいですか?
私の環境変数を見て、有望に見える次の2つを見つけました。
~# declare -p BASH_VERSINFO HOSTTYPE
declare -ar BASH_VERSINFO=([0]="5" [1]="0" [2]="11" [3]="1" [4]="release" [5]="x86_64-slackware-linux-gnu")
declare -- HOSTTYPE="x86_64"
...しかし、Bash算術の最大数が何であるかを結論付けるためにこれを解析できると本当に信頼できますか?プログラムでより良い方法が必要です。どんな提案がありますか?
ベストアンサー1
Bash算術は符号付き数字を使用します。
したがって、迅速な答えは次のようになります。
((MAX=(1<<63)-1))
しかし、スクリプトが実行されているシステムのビットに対して不可知論的であることを望んでいるので、続行します。
無差別代入は、負にオーバーフローする点に達するまでループに1を追加し続けます。しかし、これは数年かかるかもしれません! :-) より高速でエレガントな方法は、単純なビットシフトを使用することです。
符号ビットを探しましょう。つまり、1
最上位ビットから数字を探し、数に関係なく他のすべてのビットでゼロを探します。この数字を取得したら、1
数字を減算すると最大の符号付き数字が得られます。
# MIN -- the smallest signed number 0x8000...00 (it equals MAX+1)
# MAX -- the largest signed number 0x7Fff...FF <-- what we are looking for
MIN=1; until (( (MIN<<=1) < 0 )) ;do :;done
((MAX=MIN-1))
echo $MAX
Result:
9223372036854775807
またはループのない単一行です。数値の16進表現を変数に入れ、それを組み込み関数に渡すときに変数拡張を介して符号ビットをマスクしますprintf
。
printf -v MAX %x -1 && printf -v MAX %d 0x${MAX/f/7}
echo $MAX
Result:
9223372036854775807
私と異なる桁数を持つコンピュータでは、結果は異なる数値になります。
説明のために、私の場合は次のようになります。
printf "MAX %X %d\nMIN %X %d\n" $MAX $MAX $MIN $MIN
MAX 7FFFFFFFFFFFFFFF 9223372036854775807
MIN 8000000000000000 -9223372036854775808
MINに関するいくつかの注意:MINのみを使用するように制限したい場合があります((MIN=-MAX))
。そうしないと、一部の算術演算に問題が発生することがあります。
((MIN=-MAX)) ; printf "MIN %X %d\n" $MIN $MIN
MIN 8000000000000001 -9223372036854775807