ビットをシフトして整数を生成します。どこまで行けますか?
整数表現がラップされるまで(ほとんどのシェルのデフォルト)。
通常、64ビット整数はで折り返し2**63 - 1
ます。
こと0x7fffffffffffffff
か9223372036854775807
12月インチ
その数「+1」は負になります。
これはと同じです1<<63
、したがって:
$ echo "$((1<<62)) $((1<<63)) and $((1<<64))"
4611686018427387904 -9223372036854775808 and 1
その後、プロセスが再び繰り返されます。
$((1<<80000)) $((1<<1022)) $((1<<1023)) $((1<<1024)) $((1<<1025)) $((1<<1026))
結果はmod 64
、シフト値[a]に依存します。
[a] From:Intel®64 and IA-32 Architectures Software Developer's Manual:Volume 2カウントは5ビットにマスクされます(64ビットモードでREX.Wが使用されている場合は6ビット)。カウント範囲は0〜31(または64ビットモードとREX.Wが使用される場合は63)に制限されます。。
また:それは覚えて$((1<<0))
います1
$ for i in 80000 1022 1023 1024 1025 1026; do echo "$((i%64)) $((1<<i))"; done
0 1
62 4611686018427387904
63 -9223372036854775808
0 1
1 2
2 4
そのため、64の倍数にどれだけ近いかに依存します。
制限のテスト:
最大の正(および負)の整数である堅牢なテスト方法は、各1ビットを順番にテストすることです。とにかく、ほとんどのコンピューターで64未満のステップで、遅すぎることはありません。
バッシュ
最初に、フォームの最大の整数2^n
(1ビットにゼロが続く)が必要です。次のシフトで数値が負になるまで左にシフトすることで、「ラップアラウンド」とも呼ばれます。
a=1; while ((a>0)); do ((b=a,a<<=1)) ; done
どこ b
結果はあります:ループに失敗した最後のシフトの前の値。
次に、次の記号に影響を与えるものを見つけるためにあらゆることを試みる必要がありますe
。
c=$b;d=$b;
while ((c>>=1)); do
((e=d+c))
(( e>0 )) && ((d=e))
done;
intmax=$d
最大整数(intmax
)は、の最後の値から得られますd
。
マイナス側(未満0
)では、すべてのテストを繰り返しますが、折り返さずにビットを0にできる場合はテストします。
すべてのステップを印刷するテスト全体はこれです(bashの場合):
#!/bin/bash
sayit(){ printf '%020d 0x%016x\n' "$1"{,}; }
a=1; while ((a>0)) ; do((b=a,a<<=1)) ; sayit "$a"; done
c=$b;d=$b; while((c>>=1)); do((e=d+c));((e>0))&&((d=e)) ; sayit "$d"; done;
intmax=$d
a=-1; while ((a<0)) ; do((b=a,a<<=1)) ; sayit "$b"; done;
c=$b;d=$b; while ((c<-1)); do((c>>=1,e=d+c));((e<0))&&((d=e)); sayit "$d"; done
intmin=$d
printf '%20d max positive value 0x%016x\n' "$intmax" "$intmax"
printf '%20d min negative value 0x%016x\n' "$intmin" "$intmin"
sh
ほとんどすべてのシェルに変換:
#!/bin/sh
printing=false
sayit(){ "$printing" && printf '%020d 0x%016x\n' "$1" "$1"; }
a=1; while [ "$a" -gt 0 ];do b=$a;a=$((a<<1)); sayit "$a"; done
c=$b;d=$b; while c=$((c>>1)); [ "$c" -gt 0 ];do e=$((d+c)); [ "$e" -gt 0 ] && d=$e ; sayit "$d"; done;
intmax=$d
a=-1; while [ "$a" -lt 0 ];do b=$a;a=$((a<<1)); sayit "$b"; done;
c=$b;d=$b; while [ "$c" -lt -1 ];do c=$((c>>1));e=$((d+c));[ "$e" -lt 0 ] && d=$e ; sayit "$d"; done
intmin=$d
printf '%20d max positive value 0x%016x\n' "$intmax" "$intmax"
printf '%20d min negative value 0x%016x\n' "$intmin" "$intmin"
多くのシェルで上記を実行すると、
すべて(bash 2.04およびmkshを除く2**63 -1
)がこのコンピューターで()までの値を受け入れました。
attシェルを報告するのは興味深いです:
$ attsh --version
version sh (AT&T Research) 93u+ 2012-08-01
$((2^63))
ただし、kshではなくの値にエラーを出力しました。