Skrip shell yang sesuai dengan POSIX hanya diperlukan untuk mendukung integer aritmatika menggunakan bahasa shell ("hanya diperlukan aritmatika integer panjang yang ditandatangani"), jadi shell murni solusi harus meniru aritmatika titik-mengambang:
item=30
total=70
percent=$(( 100 * item / total + (1000 * item / total % 10 >= 5 ? 1 : 0) ))
100 * item / total
menghasilkan terpotong hasil dari bilangan bulat pembagian sebagai persentase.1000 * item / total % 10 >= 5 ? 1 : 0
menghitung tempat desimal ke-1, dan jika sama dengan atau lebih besar dari 5, tambahkan 1 ke hasil bilangan bulat untuk membulatkannya.- Perhatikan bahwa tidak ada perlu mengawali referensi variabel dengan
$
di dalam ekspansi aritmatika$((...))
.
Jika - bertentangan dengan premis pertanyaan - penggunaan utilitas eksternal dapat diterima:
awk
menawarkan sederhana solusi, yang, bagaimanapun, disertai dengan peringatan bahwa ia menggunakan biner presisi ganda yang sebenarnya nilai floating point dan karenanya dapat menghasilkan hasil yang tidak diharapkan dalam desimal representasi - mis., cobaprintf '%.0f\n' 28.5
, yang menghasilkan28
daripada29
yang diharapkan ):
awk -v item=30 -v total=70 'BEGIN { printf "%.0f\n", 100 * item / total }'
- Perhatikan bagaimana
-v
digunakan untuk mendefinisikan variabel untukawk
skrip, yang memungkinkan pemisahan bersih antara kutipan tunggal dan karena itu harfiahawk
skrip dan nilai apa pun yang diteruskan dari shell .
- Sebaliknya, meskipun
bc
adalah utilitas POSIX (dan karena itu dapat diharapkan hadir di sebagian besar platform mirip-Unix) dan melakukan ketepatan sewenang-wenang aritmatika, selalu terpotong hasilnya, sehingga pembulatan harus dilakukan oleh lain kegunaan;printf
, namun, meskipun pada prinsipnya utilitas POSIX, tidak diperlukan untuk mendukung penentu format floating-point (seperti yang digunakan di dalamawk
di atas), jadi berikut ini mungkin berfungsi atau tidak (dan tidak sebanding dengan masalahnya, mengingatawk
yang lebih sederhana solusi, dan mengingat bahwa masalah presisi karena aritmatika floating-point kembali ke gambar):
# !! This MAY work on your platform, but is NOT POSIX-compliant:
# `-l` tells `bc` to set the precision to 20 decimal places, `printf '%.0f\n'`
# then performs the rounding to an integer.
item=20 total=70
printf '%.0f\n' "$(bc -l <<EOF
100 * $item / $total
EOF
)"
Gunakan AWK (tanpa bash-isme):
item=30
total=70
percent=$(awk "BEGIN { pc=100*${item}/${total}; i=int(pc); print (pc-i<0.5)?i:i+1 }")
echo $percent
43
Mengambil 2 * kalkulasi persen asli dan mendapatkan modulo 2 yang memberikan kenaikan untuk pembulatan.
item=30
total=70
percent=$((200*$item/$total % 2 + 100*$item/$total))
echo $percent
43
(diuji dengan bash, ash, dash, dan ksh)
Ini adalah implementasi yang lebih cepat daripada menjalankan koproses AWK:
$ pa() { for i in `seq 0 1000`; do pc=$(awk "BEGIN { pc=100*${item}/${total}; i=int(pc); print (pc-i<0.5)?i:i+1 }"); done; }
$ time pa
real 0m24.686s
user 0m0.376s
sys 0m22.828s
$ pb() { for i in `seq 0 1000`; do pc=$((200*$item/$total % 2 + 100*$item/$total)); done; }
$ time pb
real 0m0.035s
user 0m0.000s
sys 0m0.012s
Kekuatan Sinyal Bluetooth LE Linux
Otomatisasi mysql_secure_installation dengan perintah gema melalui skrip shell