Ini adalah pertanyaan eksplorasi, artinya saya tidak sepenuhnya yakin tentang pertanyaan ini, tapi saya pikir ini tentang bilangan bulat terbesar di Bash. Bagaimanapun, saya akan mendefinisikannya secara berlebihan.
$ echo $((1<<8))
256
Saya menghasilkan bilangan bulat dengan menggeser sedikit. Seberapa jauh saya bisa pergi?
$ echo $((1<<80000))
1
Sepertinya tidak sejauh ini. (1 tidak terduga, dan saya akan kembali ke sana.) Tapi,
$ echo $((1<<1022))
4611686018427387904
masih positif. Namun, bukan ini:
$ echo $((1<<1023))
-9223372036854775808
Dan satu langkah lebih jauh,
$ echo $((1<<1024))
1
Kenapa 1? Dan mengapa berikut ini?
$ echo $((1<<1025))
2
$ echo $((1<<1026))
4
Apakah seseorang ingin menganalisis seri ini?
MEMPERBARUI
Mesin saya:
$ uname -a
Linux tomas-Latitude-E4200 4.4.0-47-generic #68-Ubuntu SMP Wed Oct 26 19:39:52 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
bash
arithmetic
Gilles 'SO- berhenti menjadi jahat'
sumber
sumber
Jawaban:
Bash menggunakan
intmax_t
variabel untuk aritmatika . Di sistem Anda panjangnya 64 bit, jadi:yang mana
dalam biner (1 diikuti oleh 62 0s). Alihkan lagi:
yang mana
dalam biner (63 0s), dalam aritmatika komplemen dua.
Untuk mendapatkan integer representable terbesar, Anda harus mengurangi 1:
yang mana
dalam biner.
Seperti keluar menunjuk di ilkkachu 's jawaban , menggeser mengambil offset modulo 64 pada 64-bit x86 CPU (apakah menggunakan
RCL
atauSHL
), yang menjelaskan perilaku yang Anda lihat:setara dengan
$((1<<0))
. Dengan demikian$((1<<1025))
adalah$((1<<1))
,$((1<<1026))
adalah$((1<<2))
...Anda akan menemukan definisi jenis dan nilai maksimum di
stdint.h
; di sistem Anda:sumber
-
memiliki prioritas lebih tinggi daripada<<
.echo $((1<<63-1))
memberi saya4611686018427387904
.$((1<<63-1))
sama dengan$(((1<<63)-1))
.Dari
CHANGES
file untukbash
2.05b:Pada mesin x86_64
intmax_t
sesuai dengan integer 64-bit yang ditandatangani. Jadi, Anda mendapatkan nilai yang berarti antara-2^63
dan2^63-1
. Di luar rentang itu Anda hanya mendapatkan wrap-arounds.sumber
-2^63
dan2^63-1
, inklusif.Pergeseran oleh 1024 memberikan satu, karena jumlah pergeseran secara efektif diambil modulo jumlah bit (64), jadi
1024 === 64 === 0
, dan1025 === 65 === 1
.Menggeser sesuatu selain a
1
memperjelas bahwa itu bukan rotasi bit, karena bit yang lebih tinggi tidak membungkus ke bagian bawah sebelum nilai shiftnya (setidaknya) 64:Mungkin perilaku ini tergantung pada sistem. The kode pesta Stephen terkait dengan menunjukkan hanya pergeseran polos, tanpa memeriksa untuk nilai tangan kanan. Jika saya ingat dengan benar, prosesor x86 hanya menggunakan enam bit terbawah dari nilai shift (dalam mode 64-bit), sehingga perilaku mungkin langsung dari bahasa mesin. Juga, saya pikir bergeser lebih dari lebar bit tidak didefinisikan dengan jelas dalam C baik (
gcc
memperingatkan untuk itu).sumber
Sampai representasi integer membungkus (default di kebanyakan shell).
Bilangan bulat 64 bit biasanya membungkus di
2**63 - 1
.Itu
0x7fffffffffffffff
atau9223372036854775807
di bulan Desember.Angka '+1' menjadi negatif.
Itu sama dengan
1<<63
, jadi:Setelah itu prosesnya berulang lagi.
Hasilnya tergantung pada
mod 64
nilai pergeseran [a] .[a] Dari: Manual Pengembang Perangkat Lunak Arsitektur Intel® 64 dan IA-32: Volume 2 Hitungannya disamarkan menjadi 5 bit (atau 6 bit jika dalam mode 64-bit dan REX.W digunakan). Kisaran hitungan dibatasi hingga 0 hingga 31 (atau 63 jika mode 64-bit dan REX.W digunakan). .
Juga: ingat bahwa
$((1<<0))
adalah1
Jadi, itu semua tergantung pada seberapa dekat angka ke kelipatan 64.
Menguji batas:
Cara kuat untuk menguji yang merupakan bilangan bulat positif (dan negatif) maksimum adalah dengan menguji setiap bit pada gilirannya. Itu kurang dari 64 langkah untuk sebagian besar komputer, itu tidak akan terlalu lambat.
pesta
Pertama kita membutuhkan bilangan bulat terbesar dari bentuk
2^n
(set 1 bit diikuti oleh nol). Kita dapat melakukannya dengan menggeser ke kiri sampai shift berikutnya membuat angka negatif, juga disebut "membungkus":Di mana
b
hasilnya: nilai sebelum shift terakhir yang gagal dalam loop.Maka kita perlu mencoba setiap bit untuk mencari tahu mana yang mempengaruhi tanda
e
:Integer maksimum (
intmax
) dihasilkan dari nilai terakhir darid
.Di sisi negatif (kurang dari
0
) kami mengulangi semua tes tetapi menguji kapan bit bisa dibuat 0 tanpa melilit.Seluruh pengujian dengan pencetakan semua langkah adalah ini (untuk bash):
SH
Diterjemahkan ke hampir semua shell:
Menjalankan hal di atas untuk banyak shell,
semua (kecuali bash 2.04 dan mksh) menerima nilai hingga (
2**63 -1
) di komputer ini.Sangat menarik untuk melaporkan bahwa shell att :
mencetak kesalahan pada nilai
$((2^63))
, bukan ksh sekalipun.sumber