Saya ingin membuat for for loop di bash dengan 0,02 sebagai peningkatan yang saya coba
for ((i=4.00;i<5.42;i+=0.02))
do
commands
done
tapi itu tidak berhasil.
bash
for
floating-point
Mehrshad
sumber
sumber
bc
, tetapi berhenti pada 4,52 mungkin sulit. gunakan saran @roaima, dapatkan var bantu dengan langkah 2, dan gunakani=$(echo $tmp_var / 100 | bc)
Jawaban:
Membaca
bash
halaman manual memberikan informasi berikut:dan kemudian kita mendapatkan bagian ini
Jadi dapat terlihat jelas bahwa Anda tidak dapat menggunakan
for
loop dengan nilai-nilai non-integer.Satu solusi mungkin hanya dengan melipatgandakan semua komponen loop Anda dengan 100, memungkinkan untuk ini di mana Anda nanti menggunakannya, seperti ini:
sumber
k=400;k<542;k+=2
itu juga menghindari masalah aritmatika floating point.bc
), melakukan proses, membuat file sementara (untuk string-sini), jalankanbc
di dalamnya (yang menyiratkan memuat perpustakaan yang dapat dieksekusi dan dibagikan, serta menginisialisasi mereka), tunggu dan bersih-bersih. Menjalankanbc
sekali untuk melakukan loop akan jauh lebih efisien.i=$(bc <<< "scale...")
ataui=$(echo "scale..." | bc)
<<<
asalnya),bash
danksh
. Perhatikan bahwa beralih ke shell lain selainbash
akan memberi Anda peningkatan kinerja yang lebih baik daripada menggunakan sintaks lainnya.<<<
(zsh, mksh, ksh93, yash) juga mendukung floating point aritmatika (zsh
,ksh93
,yash
)).Hindari loop dalam cangkang.
Jika Anda ingin melakukan aritmatika, gunakan
awk
ataubc
:Atau
Perhatikan bahwa
awk
(bertentangan denganbc
) bekerja dengandouble
representasi nomor floating point prosesor Anda (kemungkinan tipe IEEE 754 ). Akibatnya, karena angka-angka itu adalah perkiraan biner dari angka desimal itu, Anda mungkin memiliki beberapa kejutan:Jika Anda menambahkan,
OFMT="%.17g"
Anda dapat melihat alasan hilangnya0.3
:bc
tidak presisi sewenang-wenang sehingga tidak memiliki masalah seperti ini.Perhatikan bahwa secara default (kecuali jika Anda memodifikasi format output dengan
OFMT
atau menggunakanprintf
dengan spesifikasi format eksplisit),awk
digunakan%.6g
untuk menampilkan angka floating point, jadi akan beralih ke 1e6 dan di atasnya untuk angka floating point di atas 1.000.000 dan memotong bagian fraksional untuk angka tinggi (100000.02 akan ditampilkan sebagai 100000).Jika Anda benar-benar perlu menggunakan shell loop, karena misalnya Anda ingin menjalankan perintah khusus untuk setiap iterasi dari loop itu, baik menggunakan shell dengan dukungan aritmatika floating point seperti
zsh
,yash
atauksh93
atau menghasilkan daftar nilai dengan satu perintah seperti di atas (atauseq
jika tersedia) dan lewati outputnya.Suka:
Atau:
kecuali Anda menekan batas angka floating point prosesor Anda,
seq
menangani kesalahan yang ditimbulkan oleh pendekatan floating point lebih anggun daripadaawk
versi di atas.Jika Anda tidak memiliki
seq
(perintah GNU), Anda dapat membuat yang lebih dapat diandalkan sebagai fungsi seperti:Itu akan bekerja lebih baik untuk hal-hal seperti
seq 100000000001 0.000000001 100000000001.000000005
. Namun perlu dicatat bahwa memiliki angka dengan presisi tinggi yang sewenang-wenang tidak akan banyak membantu jika kita akan meneruskannya ke perintah yang tidak mendukungnya.sumber
unset IFS
pada contoh pertama?IFS=$'\n'
tetapi itu tidak berhasil di semua shell. AtauIFS='<a-litteral-newline-here>'
tapi itu tidak terlalu terbaca. Atau kita dapat membagi kata-kata sebagai gantinya (spasi, tab, baris baru) seperti yang Anda dapatkan dengan nilai default $ IFS atau jika Anda menghapus IFS dan juga berfungsi di sini.IFS
, karena kita tahu bahwaseq
output tidak memiliki ruang yang harus kita hindari pemisahan. Sebagian besar ada di sana untuk memastikan Anda menyadari bahwa contoh ini tergantungIFS
, yang mungkin penting untuk perintah pembuatan daftar yang berbeda.Gunakan "seq" - mencetak urutan angka
seq INCREMENT PERTAMA TERAKHIR
sumber
Seperti yang disarankan orang lain, Anda dapat menggunakan bc:
sumber