Saya memiliki kode kerja berikut:
largest_prime=1
for number_under_test in {1..100}
do
is_prime=true
factors=''
for ((divider = 2; divider < number_under_test-1; divider++));
do
remainder=$(($number_under_test % $divider))
[ $remainder == 0 ] && [ is_prime ] && is_prime=false && factors+=$divider' '
done
[ $is_prime == true ] && echo "${number_under_test} is prime!" || echo "${number_under_test} is NOT prime (factors= $factors)" [ $is_prime == true ] && largest_prime=$number_under_test
done
printf "\nLargest Prime= $largest_prime\n"
Kode ini berjalan cepat adalah 0,194 detik. Namun saya menemukan && is_prime= false
sedikit sulit untuk dibaca dan itu bisa terlihat (dengan mata yang tidak terlatih) seolah-olah sedang diuji daripada ditetapkan yang memang demikian. Jadi saya mencoba mengubah &&
menjadi if...then
dan ini berhasil - tetapi 75 kali lebih lambat pada 14,48 detik. Ini paling terlihat pada angka yang lebih tinggi.
largest_prime=1
for number_under_test in {1..100}
do
is_prime=true
factors=''
for ((divider = 2; divider < number_under_test-1; divider++));
do
remainder=$(($number_under_test % $divider))
if ([ $remainder == 0 ] && [ $is_prime == true ]); then
is_prime=false
factors+=$divider' '
fi
done
[ $is_prime == true ] && echo "${number_under_test} is prime!" || echo "${number_under_test} is NOT prime (factors= $factors)" [ $is_prime == true ] && largest_prime=$number_under_test
done
printf "\nLargest Prime= $largest_prime\n"
Apakah ada kejelasan blok tanpa kelambatan?
Pembaruan (1/4/2015 10:40 pagi EST)
Umpan balik yang bagus! Saya sekarang menggunakan yang berikut ini. Ada tanggapan lain?
largest_prime=1
separator=' '
for number_under_test in {1..100}; {
is_prime=true
factors=''
for ((divider = 2; divider < (number_under_test/2)+1; divider++)) {
remainder=$(($number_under_test % $divider))
if [ $remainder == 0 ]; then
is_prime=false
factors+=$divider' '
fi
}
if $is_prime; then
printf "\n${number_under_test} IS prime\n\n"
largest_prime=$number_under_test
else
printf "${number_under_test} is NOT prime, factors are: "
printf "$factors\n"
fi
}
printf "\nLargest Prime= $largest_prime\n"
shell
shell-script
Michael Durrant
sumber
sumber
Largest Prime= 100
di komputer saya.number_under_test/2
alih-alih hingganumber_under_test-1
: Tidak ada faktor angka n lebih besar dari n / 2, sehingga Anda masih akan menemukan semua faktor untuk bilangan non-prima dengan melakukan ini. (Juga jika Anda hanya tertarik untuk menguji primeness, itu akan cukup untuk beralih ke sqrt (n), tetapi Bash tetap memiliki fungsi(number_under_test/2)+1
untuk memungkinkan{}
tidak benar-benar diperlukan setelahthen
klausa karenathen
sudah berfungsi sebagai operator pengelompokan (bersama denganelif
,else
ataufi
). Bahkan, dalam beberapa shell, Anda dapat menulis, misalnya,for i in 1 2 3; { echo $i; }
tanpado
ataudone
.Jawaban:
Itu karena Anda menghasilkan sub-shell setiap kali:
Hapus saja tanda kurung
Jika Anda ingin mengelompokkan perintah, ada sintaks untuk melakukannya di shell saat ini :
(tanda titik koma diperlukan, lihat manual )
Catatan yang
[ is_prime ]
tidak sama dengan[ $is_prime == true ]
: Anda bisa menulisnya secara sederhana$is_prime
(tanpa tanda kurung) yang akan memanggil bash built-intrue
ataufalse
perintah.[ is_prime ]
adalah tes dengan satu argumen, string "is_prime" - ketika[
diberikan argumen tunggal, hasilnya berhasil jika argumen tidak kosong, dan string literal selalu tidak kosong, maka selalu "benar".Untuk keterbacaan, saya akan mengubah baris yang sangat panjang
untuk
Jangan meremehkan spasi putih untuk meningkatkan kejelasan.
sumber
largest_prime=$number_under_test
harus di cabang saat itu (kesalahan yang sama ada di aslinya)[
menjalankan program yang secara harfiah disebut[
, sedangkan[[
diimplementasikan dalam shell - maka itu akan lebih cepat. Cobatime for ((i = 0; $i < 1000; i++)); do [ 1 ]; done
dan bandingkan[[
. Lihat pertanyaan SO ini untuk info lebih lanjut.[
, itu builtin. Dari prompt shell, ketiktype -a [
danhelp [
which [
masih kembali/usr/bin/[
. Saya juga baru menyadari bahwa saya menyiratkan zsh adalah sama; bagi saya yang mengatakan itu adalah builtin. Tetapi kemudian ... mengapa [[lebih cepat?command -v
adalahwhich
alternatif lain yang bagus ; lihat juga di sini .Saya pikir Anda bekerja terlalu keras pada fungsi Anda itu. Mempertimbangkan:
Aritmatika shell cukup mampu mengevaluasi kondisi bilangan bulat sendiri. Jarang membutuhkan terlalu banyak tes dan / atau tugas luar. Satu
while
loop ini menduplikasi loop bersarang dengan cukup baik:Itu tidak banyak mencetak, tentu saja, saya tidak menulis terlalu banyak, tetapi, misalnya mengatur langit-langit menjadi 16 daripada 101 seperti yang tertulis di atas dan ...
Pasti melakukan pekerjaan. Dan sangat sedikit yang dibutuhkan untuk memperkirakan output Anda:
Hanya melakukan itu daripada
echo
...Ini berfungsi di
busybox
. Ini sangat portabel, cepat, dan mudah digunakan.Masalah subkulit Anda akan terjadi di sebagian besar shell, tetapi, sejauh ini , paling akut di
bash
shell. Saya bergantian antara melakukan... dan cara saya menulisnya di atas dalam beberapa kerang untuk langit-langit 101 dan
dash
melakukannya tanpa subkulit dalam 0,017 detik dan dengan subkulit dalam 1,8 detik.busybox
.149 dan 2, zsh .149 dan 4,bash
.35 dan 6, danksh93
dalam .149 dan .160.ksh93
tidak membayar untuk subkulit seperti kulit kerang lainnya. Jadi mungkin masalahnya tidak terlalu banyak subshell seperti shell .sumber
[ "$((...))" -eq "$((...))" ]
atas(( (...) == (...) ))
? Apakah yang terakhir kurang portabel?[ "$((...))" -eq "$((...)) ]
bekerja dalam shell yang tidak membutuhkan waktu 15 detik untuk menjalankan program, dan yang lainnya tidak. Jika keuntungan satu sama lain dipertanyakan sama sekali, maka itu hanya dapat memberikan keunggulan bagi yang pertama, yang berarti tidak pernah ada alasan yang baik untuk menggunakannya(( (...) == (...) ))
.(( ... ))
. Aku tersanjung, tapi saya tidak tidak memiliki pengetahuan rinci. (Ingat, akulah yang baru saja bertanya apakah(( ... ))
itu kurang portabel.) Jadi aku benar-benar tidak masuk akal dengan balasanmu. : - / Bisakah Anda menjadi sedikit lebih eksplisit?"$((...))"
ini POSIX-ditentukan dan yang lainnya adalah ekstensi shell. Kerang POSIX cukup mampu. Bahkandash
danposh
dengan benar akan menangani tes cabang seperti"$((if_true ? (var=10) : (var=5) ))"
dan selalu menetapkan$var
dengan benar.busybox
istirahat di sana - selalu mengevaluasi kedua belah pihak terlepas dari$if_true
nilai.