次の作業コードがあります。
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"
このコードは0.194秒の高速で実行されます。しかし、&& is_prime= false
読書が少し難しく、(訓練されていない目には)設定されているのではなく、テストされているようです。それで&&
an に変更してみたところif...then
効果がありました。しかし、14.48秒で75倍遅かった。数字が高いほど最も目立つ。
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"
鈍く見えずにブロックをシャープに保つ方法はありますか?
更新済み(2015年1月4日午前10時40分ET)
良いフィードバック!現在、以下を使用しています。他の提案はありませんか?
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"
答え1
その理由は、毎回サブシェルを生成するからです。
if ([ $remainder == 0 ] && [ $is_prime == true ]); then
かっこを削除するだけです
if [ $remainder == 0 ] && [ $is_prime == true ]; then
コマンドをグループ化するには、次の構文を使用します。現在のシェル:
if { [ $remainder == 0 ] && [ $is_prime == true ]; }; then
(末尾のセミコロンが必要です。手動)
これは[ is_prime ]
以下とは異なります。角かっこなしで[ $is_prime == true ]
簡単に書くと、bash組み込みまたはコマンドが呼び出されます。 1つの引数、文字列 "is_prime"を取るテストです。引数が与えられたときに引数が空でない場合、結果は成功し、リテラル文字列は常に空ではないため、常に「true」です。$is_prime
true
false
[ is_prime ]
[
読みやすくするために非常に長い行を変更します。
[ $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
到着
if [ $is_prime == true ]; then
echo "${number_under_test} is prime!"
else
echo "${number_under_test} is NOT prime (factors= $factors)"
# removed extraneous [ $is_prime == true ] test that you probably
# didn't notice off the edge of the screen
largest_prime=$number_under_test
fi
明確さを高めるためにスペースを過小評価しないでください。
答え2
私の考えでは、あなたがあなたの役割をとても懸命にやっていると思います。考慮する:
unset num div lprime; set -- "$((lprime=(num=(div=1))))"
while [ "$(( num += ! ( div *= ( div <= num ) ) ))" -eq \
"$(( num *= ( div += 1 ) <= 101 ))" ] && {
set "$(( ! ( num % div ) * div ))" "$@"
shift "$(( ! $1 + ( $1 == 1 ) * $# ))"
}; do [ "$div" -gt "$num" ] && echo "$*"
done
シェル操作は、それ自体が整数条件を評価する能力に非常に優れています。あまりにも多くのテストや外部の課題が必要な場合はほとんどありません。このwhile
ループはネストされたループを見事に複製します。
あまりあまり印刷されないだろうし、もちろんあまり書かなかったけど、例えば上に書かれたように101ではなく16に上限を設定して...
2
3
4 2
5
6 3 2
7
8 4 2
9 3
10 5 2
11
12 6 4 3 2
13
14 7 2
15 5 3
確かにその仕事をしています。出力をおおよその計算にはほとんど必要ありません。
...
do [ "$div" -eq "$num" ] && shift &&
printf "$num ${1+!}= prime.${1+\t%s\t%s}\n" \
"factors= $*" \
"lprime=$(( lprime = $# ? lprime : num ))"
done
ちょうど代わりにしてみてくださいecho
...
1 = prime.
2 = prime.
3 = prime.
4 != prime. factors= 2 lprime=3
5 = prime.
6 != prime. factors= 3 2 lprime=5
7 = prime.
8 != prime. factors= 4 2 lprime=7
9 != prime. factors= 3 lprime=7
10 != prime. factors= 5 2 lprime=7
11 = prime.
12 != prime. factors= 6 4 3 2 lprime=11
13 = prime.
14 != prime. factors= 7 2 lprime=13
15 != prime. factors= 5 3 lprime=13
これはbusybox
非常に移植性があり、迅速かつ使いやすいです。
サブシェルの問題はほとんどのシェルで発生しますが、次のように実行されます。遠く、殻の中で最も鋭いものですbash
。交互に行きます。
( [ "$div" -gt "$num" ] ) && ...
...上で制限がdash
101の複数のシェルに作成しましたが、サブシェルがない場合は0.017秒、サブシェルがあれば1.8秒で完了しました。busybox
.149と2、zsh .149と4、bash
.35と6、ksh93
.149と.160。ksh93
他のシェルのようにサブシェルを分岐する必要はありません。したがって、問題はサブシェルにあるのではありませんシェル。