Saya sering menggunakan bc
utilitas untuk mengubah hex menjadi desimal dan sebaliknya. Namun, selalu sedikit trial and error bagaimana ibase
dan obase
harus dikonfigurasi. Sebagai contoh di sini saya ingin mengonversi nilai hex C0 ke desimal:
$ echo "ibase=F;obase=A;C0" | bc
180
$ echo "ibase=F;obase=10;C0" | bc
C0
$ echo "ibase=16;obase=A;C0" | bc
192
Apa logikanya di sini? obase
( A
dalam contoh ketiga saya) harus dalam basis yang sama dengan nilai yang dikonversi ( C0
dalam contoh saya) dan ibase
( 16
dalam contoh ketiga saya) harus di basis di mana saya mengkonversi?
Jawaban:
Apa yang sebenarnya ingin Anda katakan adalah:
untuk hex-to-desimal, dan:
untuk desimal ke hex.
Anda tidak perlu memberikan keduanya
ibase
danobase
untuk konversi apa pun yang melibatkan angka desimal, karena pengaturan ini default ke 10.Anda tidak perlu memberikan baik untuk konversi seperti biner-to-hex. Dalam hal ini, saya merasa paling mudah untuk memahami sesuatu jika Anda memberi
obase
pertama:Jika Anda memberi
ibase
pertama sebagai gantinya, itu mengubah interpretasiobase
pengaturan berikut , sehingga perintahnya harus:Ini karena dalam urutan ini,
obase
nilai ditafsirkan sebagai angka biner, jadi Anda harus memberikan 10.000₂ = 16 untuk mendapatkan output dalam hex. Itu canggung.Sekarang mari kita cari tahu mengapa tiga contoh Anda berperilaku seperti itu.
echo "ibase=F;obase=A;C0" | bc
180
Itu menetapkan basis input ke 15 dan basis output ke 10, karena nilai satu digit ditafsirkan dalam hex, menurut POSIX . Ini meminta
bc
Anda memberi tahu Anda apa yang C0₁₅ ada di basis A₁₅ = 10, dan menjawab dengan benar 180 this, meskipun ini jelas bukan pertanyaan yang ingin Anda tanyakan.echo "ibase=F;obase=10;C0" | bc
C0
Ini adalah konversi nol di basis 15.
Mengapa? Pertama, karena
F
digit tunggal ditafsirkan dalam hex, seperti yang saya tunjukkan dalam contoh sebelumnya. Tetapi sekarang setelah Anda mengaturnya ke basis 15, pengaturan basis output berikut ditafsirkan seperti itu, dan 10₁₅ = 15, sehingga Anda memiliki konversi nol dari C0₁₅ ke C0₁₅.Itu benar, output tidak dalam hex seperti yang Anda asumsikan, itu di base 15!
Anda dapat membuktikan ini pada diri Anda sendiri dengan mencoba mengonversi
F0
alih-alihC0
. Karena tidak adaF
digit di basis 15,bc
klem keE0
, dan berikanE0
sebagai output.echo "ibase=16; obase=A; C0"
192
Ini adalah satu-satunya dari tiga contoh Anda yang mungkin memiliki penggunaan praktis.
Ini mengubah basis input menjadi hex terlebih dahulu , sehingga Anda tidak perlu lagi menggali spec POSIX untuk memahami mengapa
A
ditafsirkan sebagai hex, 10 dalam hal ini. Satu-satunya masalah dengan itu adalah redundan untuk mengatur basis output ke A₁₆ = 10, karena itulah nilai defaultnya.sumber
Pengaturan
ibase
berarti Anda perlu mengaturobase
basis yang sama. Menjelaskan contoh Anda akan menunjukkan ini:Anda mengatur
bc
untuk mempertimbangkan nomor input sebagaimana diwakili dalam basis 15 dengan "ibase = F". "obase = A" mengatur nomor output ke basis 10, yang merupakan default.bc
membaca C0 sebagai angka dasar 15: C = 12. 12 * 15 = 180.Dalam yang satu ini, Anda menetapkan input ke basis 15, dan output ke 10 - di basis 15, sehingga basis output adalah 15. C0 input di basis 15 adalah C0 output di basis 15.
Atur input ke basis 16, output ke basis 10 (A dalam basis 16 adalah 10 di basis 10).
C0 dikonversi ke basis 10 adalah: 12 * 16 = 192
Aturan pribadi saya adalah mengatur obase terlebih dahulu, sehingga saya bisa menggunakan basis 10. Kemudian atur ibase, juga menggunakan basis 10.
Catatan yang
bc
memang memiliki pengecualian ironis:ibase=A
danobase=A
selalu menetapkan input dan output ke basis 10. Daribc
halaman manual:Perilaku ini diabadikan dalam spesifikasi
bc
: Dari spesifikasi OpenGroup 2004bc
:Itu sebabnya
ibase=F
pengaturan mengubah basis input Anda ke basis 15, dan mengapa saya menyarankan untuk selalu mengatur basis menggunakan basis 10. Hindari membingungkan diri sendiri.sumber
Semua angka ditafsirkan oleh GNU bc sebagai basis input saat ini yang berlaku untuk pernyataan nomor muncul. Ketika Anda menggunakan digit di luar input saat ini mengartikannya sebagai digit tertinggi yang tersedia di basis (9 dalam desimal) ketika bagian dari beberapa digit angka, atau sebagai nilai normalnya ketika digunakan sebagai angka digit tunggal (
A
== 10 dalam desimal).Dari manual GNU bc :
Namun, Anda harus menyadari bahwa standar POSIX hanya mendefinisikan perilaku ini untuk penugasan ke
ibase
danobase
, dan tidak dalam konteks lain.Dari spesifikasi SUS pada bc :
Faktor utama yang Anda lewatkan adalah bahwa F sebenarnya bukan enam belas, tetapi sebenarnya lima belas, jadi ketika Anda menetapkan ibase = F Anda menetapkan basis input ke lima belas.
Oleh karena itu, untuk portable mengatur Ibase ke heksadesimal dari negara yang tidak dikenal, karena itu Anda perlu menggunakan dua pernyataan:
ibase=A; ibase=16
. Namun, di awal program Anda dapat mengandalkannya sebagai desimal dan cukup digunakanibase=16
.sumber
ibase=A; ibase=16
.Itu selalu disarankan untuk mengatur
ibase
danobase
menggunakan nomor satu digit, daripada angka seperti16
, karena menurutbc
halaman manual,Ini berarti bahwa
A,B,...,F
selalu memiliki nilai10,11,...,15
masing-masing, terlepas dari apa nilainyaibase
. Anda juga dapat menggunakanF+1
untuk menentukan nomor16
. Misalnya, Anda sebaiknya menulisalih-alih menulis
echo "ibase=16; obase=A; C0" | bc
untuk menentukan basis input16
dan basis output10
. Atau misalnya, jika Anda menginginkan keduanyaibase
danobase
berusia 16 tahun, sebaiknya Anda gunakanalih-alih menggunakan
ibase=16; obase=10
. Demikian pula, jika Anda akan memasukkan angka-angka di basis 14 dan menghasilkannya di basis 16, gunakanMeskipun bentuk mandi memiliki hasil yang sama, yang pertama kurang rawan kesalahan, sedangkan yang terakhir dapat menyebabkan lebih banyak kebingungan dan kesalahan.
Perbedaan antara dua bentuk terutama menjadi lebih jelas, ketika Anda berada di lingkungan eksekusi
bc
, atau Anda akan menulis perhitungan Anda dalam file, dan kemudian meneruskan file itubc
sebagai argumen. Dalam situasi seperti itu, Anda mungkin harus mengubah nilaiibase
danobase
beberapa kali, dan menggunakan formulir yang terakhir, dapat menyebabkan kebingungan dan kesalahan serius. (mengalaminya)sumber