Biraz kaydırarak bir tamsayı üretir. Ne kadar ileri gidebilirim?
Tamsayı gösterimi tamamlanıncaya kadar (çoğu kabukta varsayılan).
64 bitlik bir tamsayı genellikle konumunda sarar 2**63 - 1
.
Bu 0x7fffffffffffffff
ya 9223372036854775807
da aralıkta.
Bu '+1' sayısı negatif olur.
Bu, aynı 1<<63
şekilde:
$ echo "$((1<<62)) $((1<<63)) and $((1<<64))"
4611686018427387904 -9223372036854775808 and 1
Bundan sonra işlem tekrarlanır.
$((1<<80000)) $((1<<1022)) $((1<<1023)) $((1<<1024)) $((1<<1025)) $((1<<1026))
Sonuç mod 64
, kayma değerinin [a] değerine bağlıdır .
[a] Kimden: Intel® 64 ve IA-32 Mimarlar Yazılım Geliştirici Kılavuzu: Cilt 2 Sayım 5 bit olarak maskelenir (veya 64 bit modunda ve REX.W kullanılıyorsa 6 bit). Sayım aralığı 0 ila 31 (veya 64 bit modu ve REX.W kullanılıyorsa 63) ile sınırlıdır. .
Ayrıca: hatırlamak $((1<<0))
olduğunu1
$ 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
Yani, her şey sayının 64'ün katına ne kadar yakın olduğuna bağlıdır.
Sınırı test etme:
Maksimum pozitif (ve negatif) tamsayı olan testin sağlam yolu, her bir biti sırayla test etmektir. Zaten çoğu bilgisayar için 64 adımdan az, çok yavaş olmayacak.
darbe
İlk önce formun en büyük tamsayısına ihtiyacımız var 2^n
(1 bitlik set ve ardından sıfırlar). Bunu, bir sonraki vardiyaya "etrafa sarın" olarak da adlandırılan negatif olana kadar sola kaydırarak yapabiliriz :
a=1; while ((a>0)); do ((b=a,a<<=1)) ; done
b
Sonuç nerede : döngüde başarısız olan son vardiyadan önceki değer.
O zaman hangisinin işaretini etkilediğini bulmak için her şeyi denememiz gerekir e
:
c=$b;d=$b;
while ((c>>=1)); do
((e=d+c))
(( e>0 )) && ((d=e))
done;
intmax=$d
Maksimum tamsayı ( intmax
), öğesinin son değerinden kaynaklanır d
.
Negatif tarafta (daha az 0
) tüm testleri tekrarlıyoruz, ancak etrafına sarılmadan bir bitin 0 yapılabileceğini test ediyoruz.
Tüm adımların yazdırılmasıyla yapılan bütün bir test şudur (bash için):
#!/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
Neredeyse tüm kabuklara çevrilir:
#!/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"
Birçok kabuk için yukarıdakileri çalıştırmak,
hepsi (bash 2.04 ve mksh hariç 2**63 -1
) bu bilgisayarda ( ) 'ye kadar olan değerleri kabul etti .
Att kabuğunun rapor edilmesi ilginçtir :
$ attsh --version
version sh (AT&T Research) 93u+ 2012-08-01
$((2^63))
olsa da, ksh değerlerinde bir hata yazdırdı .