Saya mencoba untuk membagi dua lebar gambar dalam skrip Bash, tetapi bash memberi saya 0
hasilnya :
RESULT=$(($IMG_WIDTH/$IMG2_WIDTH))
Saya mempelajari panduan Bash dan saya tahu saya harus menggunakan bc
, dalam semua contoh di internet yang mereka gunakan bc
. Diecho
Aku mencoba untuk menempatkan hal yang sama di saya SCALE
, tapi tidak berhasil.
Berikut adalah contoh yang saya temukan di tutorial:
echo "scale=2; ${userinput}" | bc
Bagaimana saya bisa membuat Bash memberi saya pelampung 0.5
?
bash
floating-point
arithmetic-expressions
Medya Gh
sumber
sumber
Jawaban:
Kamu tidak bisa bash hanya melakukan integer; Anda harus mendelegasikan ke alat seperti
bc
.sumber
VAR=$(echo "scale=2; $IMG_WIDTH/$IMG2_WIDTH" | bc)
atauVAR=$(bc <<<"scale=2;$IMG_WIDTH/$IMG2_WIDTH")
tanpa $ (()) (tanda kurung ganda); yang diperluas oleh bash sebelum menjalankan perintahkamu bisa melakukan ini:
PEMBARUAN
20130926
: Anda dapat menggunakan:sumber
bc -l <<< 'scale=2; 100/3'
Unless specifically mentioned the scale of the result is the maximum scale of the expressions involved.
Dan ada catatan tambahan untuk/
operator:The scale of the result is the value of the variable scale.
bc <<< 'scale=1; 1*3.00001'
skala benar-benar 5 untuk beberapa alasan,bc <<< 'scale=1; 1/3.000001'
skala adalah 1. Menariknya, membaginya dengan 1 set langsung:bc <<< 'scale=1; 1*3.00001/1'
skala adalah 1pesta
Seperti dicatat oleh orang lain,
bash
tidak mendukung aritmatika titik mengambang, meskipun Anda bisa memalsukannya dengan beberapa tipuan desimal tetap, misalnya dengan dua desimal:Keluaran:
Lihat jawaban Nilfred untuk pendekatan yang serupa tetapi lebih ringkas.
Alternatif
Selain yang disebutkan
bc
danawk
alternatif ada juga yang berikut:clisp
dengan output dibersihkan:
atau melalui stdin:
dc
kalkulator genius cli
ghostscript
gnuplot
jq
Atau:
ksh
lua
atau melalui stdin:
maksimal
dengan output dibersihkan:
simpul
oktaf
perl
python2
python3
R
dengan output dibersihkan:
rubi
wcalc
Dengan output yang dibersihkan:
zsh
unit
Dengan output yang kompak:
Sumber lainnya
Stéphane Chazelas menjawab pertanyaan serupa di Unix.SX.
sumber
echo 1/3 | node -p
pendek.Meningkatkan sedikit jawaban dari marvin:
bc tidak datang selalu sebagai paket yang diinstal.
sumber
exit
mencegah agar tidak membaca dari aliran inputnya. Saya juga menyarankan menggunakan-v
bendera awk untuk mencegah sindrom tusuk gigi. Jadi:RESULT=$(awk -v dividend="${IMG_WIDTH}" -v divisor="${IMG2_WIDTH}" 'BEGIN {printf "%.2f", dividend/divisor; exit(0)}')
RESULT=$(awk '{printf("result= %.2f\n",$1/$2)}' <<<" $IMG_WIDTH $IMG2_WIDTH "
.bc
adalah bagian dari POSIX, biasanya sudah diinstal sebelumnya.Anda dapat menggunakan bc dengan
-l
opsi (huruf L)sumber
-l
pada sistem saya, bc tidak melakukan matematika floating point.Sebagai alternatif untuk bc, Anda dapat menggunakan awk dalam skrip Anda.
Sebagai contoh:
Dalam contoh di atas, "% .2f" memberi tahu fungsi printf untuk mengembalikan angka floating point dengan dua digit setelah tempat desimal. Saya menggunakan gema untuk pipa dalam variabel sebagai bidang karena awk beroperasi dengan benar pada mereka. "$ 1" dan "$ 2" merujuk ke input bidang pertama dan kedua ke awk.
Dan Anda dapat menyimpan hasilnya karena beberapa variabel lain menggunakan:
sumber
Ini adalah waktu yang tepat untuk mencoba zsh, superset (hampir) bash, dengan banyak fitur bagus tambahan termasuk matematika floating point. Berikut adalah contoh Anda di zsh:
Posting ini dapat membantu Anda: bash - Layak beralih ke zsh untuk penggunaan biasa?
sumber
Nah, sebelum float adalah waktu di mana logika desimal tetap digunakan:
Baris terakhir adalah bashim, jika tidak menggunakan bash, coba kode ini sebagai gantinya:
Alasan di balik kode adalah: kalikan dengan 100 sebelum bagi untuk mendapatkan 2 desimal.
sumber
Jika Anda menemukan varian preferensi Anda, Anda juga dapat membungkusnya menjadi suatu fungsi.
Di sini saya membungkus beberapa bashism ke dalam fungsi div:
Satu liner:
Atau multi baris:
Sekarang Anda memiliki fungsi
dan menggunakannya seperti
MEMPERBARUI Saya menambahkan skrip kecil yang memberi Anda operasi dasar dengan angka floating point untuk bash:
Pemakaian:
Dan di sini skripnya:
sumber
local _d=${3:-2}
lebih sederhanaIni bukan benar-benar titik mengambang, tetapi jika Anda menginginkan sesuatu yang menetapkan lebih dari satu hasil dalam satu doa ...
menghitung luas dan diameter lingkaran yang radiusnya diberikan dalam $ 1
sumber
Ada beberapa skenario di mana Anda tidak dapat menggunakan bc karena itu mungkin tidak ada, seperti dalam beberapa versi pengurangan busybox atau sistem embedded. Dalam kasus apa pun, membatasi ketergantungan luar selalu merupakan hal yang baik untuk dilakukan sehingga Anda selalu dapat menambahkan nol ke angka yang dibagi dengan (pembilang), yang sama dengan mengalikan dengan kekuatan 10 (Anda harus memilih kekuatan 10 sesuai dengan presisi yang Anda butuhkan), yang akan membuat output divisi bilangan bulat. Setelah bilangan bulat itu memperlakukannya sebagai string dan posisikan titik desimal (memindahkannya dari kanan ke kiri) beberapa kali sama dengan kekuatan sepuluh Anda mengalikan pembilang dengan. Ini adalah cara sederhana untuk mendapatkan hasil float dengan hanya menggunakan angka integer.
sumber
Meskipun Anda tidak dapat menggunakan pembagian titik mengambang di Bash, Anda dapat menggunakan pembagian titik tetap. Yang perlu Anda lakukan adalah mengalikan bilangan bulat Anda dengan kekuatan 10 dan kemudian membagi bagian bilangan bulat dan menggunakan operasi modulo untuk mendapatkan bagian fraksional. Pembulatan sesuai kebutuhan.
sumber
Aku tahu ini sudah tua, tapi terlalu menggoda. jadi, jawabannya adalah: Anda tidak bisa ... tetapi Anda bisa. mari kita coba ini:
seperti itu Anda mendapatkan 2 digit setelah titik, terpotong (sebut saja pembulatan ke yang lebih rendah, haha) dalam bash murni (tidak perlu meluncurkan proses lain). tentu saja, jika Anda hanya perlu satu digit setelah poin Anda kalikan dengan 10 dan lakukan modulo 10.
apa yang dilakukan:
bonus track : bc versi x 1000 membutuhkan 1,8 detik di laptop saya, sedangkan bash murni butuh 0,016 detik.
sumber
Cara melakukan perhitungan floating point di bash:
Alih-alih menggunakan "di sini string " (
<<<
) denganbc
perintah, seperti salah satu contoh yang paling banyak dipilih , inilahbc
contoh floating point favorit saya , langsung dariEXAMPLES
bagianbc
halaman manual (lihatman bc
untuk halaman manual).Sebelum kita mulai, tahu bahwa persamaan untuk pi adalah:
pi = 4*atan(1)
.a()
di bawah ini adalahbc
fungsi matematika untukatan()
.Ini adalah bagaimana menyimpan hasil perhitungan floating point ke dalam variabel bash - dalam hal ini menjadi variabel yang disebut
pi
. Perhatikan bahwascale=10
set jumlah angka desimal presisi menjadi 10 dalam hal ini. Setiap angka desimal setelah tempat ini terpotong .Sekarang, untuk memiliki satu baris kode yang juga mencetak nilai variabel ini, cukup tambahkan
echo
perintah sampai akhir sebagai perintah tindak lanjut, sebagai berikut. Perhatikan pemotongan pada 10 tempat desimal, seperti yang diperintahkan:Akhirnya, mari kita lakukan pembulatan. Di sini kita akan menggunakan
printf
fungsi untuk membulatkan ke 4 tempat desimal. Perhatikan bahwa3.14159...
putaran sekarang ke3.1416
. Karena kita membulatkan, kita tidak perlu lagi menggunakanscale=10
untuk memotong ke 10 tempat desimal, jadi kita hanya akan menghapus bagian itu. Inilah solusi akhirnya:Berikut ini adalah aplikasi hebat lainnya dan demo dari teknik-teknik di atas: mengukur dan mencetak run-time.
Perhatikan bahwa
dt_min
dibulatkan dari0.01666666666...
ke0.017
:Terkait:
sumber
Gunakan kalk. Ini contoh termudah yang saya temukan:
sumber
Bagi mereka yang mencoba menghitung persentase dengan jawaban yang diterima, tetapi kehilangan presisi:
Jika Anda menjalankan ini:
Anda
99.00
hanya mendapatkan , yang kehilangan presisi.Jika Anda menjalankannya seperti ini:
Sekarang kamu mengerti
99.99
.Karena Anda scaling hanya pada saat mencetak.
Lihat di sini
sumber
** Matematika floating point aman injeksi di bash / shell **
Catatan: Fokus dari jawaban ini adalah memberikan ide untuk solusi aman injeksi untuk melakukan matematika dalam bash (atau cangkang lainnya). Tentu saja, hal yang sama dapat digunakan, dengan sedikit penyesuaian untuk melakukan pemrosesan string lanjutan, dll.
Sebagian besar solusi yang disajikan, membangun scriptlet kecil dengan cepat, menggunakan data eksternal (variabel, file, baris perintah, variabel lingkungan). Input eksternal dapat digunakan untuk menyuntikkan kode berbahaya ke mesin, banyak di antaranya
Di bawah ini adalah perbandingan penggunaan berbagai bahasa untuk melakukan perhitungan matematika dasar, di mana hasilnya adalah floating point. Ini menghitung A + B * 0,1 (sebagai titik mengambang).
Semua solusi mencoba menghindari membuat skrip dinamis, yang sangat sulit untuk dipelihara, Alih-alih mereka menggunakan program statis, dan meneruskan parameter ke variabel yang ditunjuk. Mereka akan dengan aman menangani parameter dengan karakter khusus - mengurangi kemungkinan injeksi kode. Pengecualian adalah 'BC' yang tidak menyediakan fasilitas input / output
Pengecualian adalah 'bc', yang tidak menyediakan input / output, semua data datang melalui program di stdin, dan semua output masuk ke stdout. Semua perhitungan dijalankan dalam kotak pasir, yang tidak memungkinkan efek samping (membuka file, dll.). Secara teori, injeksi aman menurut desain!
sumber
python3 -c 'import sys ; *a, = map(float, sys.argv[1:]) ; print(a[0] + a[1]*0.1 + a[2])' "$A" "$B"
"4200.0" ==> 4205.63di sini adalah perintah awk: -F = pemisah bidang == +
sumber