我有以下工作代码:
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
有点难以阅读,并且它看起来(对于未经训练的人来说)就好像它正在被测试而不是被设置,这就是它的作用。所以我尝试将 改为&&
anif...then
并且这有效 - 但速度慢了 75 倍,为 14.48 秒。它在较高的数字上最为明显。
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)
很好的反馈!我现在正在使用以下内容。还有其他反馈意见吗 ?
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
那是因为你每次都会生成一个子 shell:
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 ]
:您可以简单地编写它$is_prime
(不带括号),这将调用 bash 内置命令true
或false
命令。
[ is_prime ]
是一个带有一个参数的测试,字符串“is_prime”——当[
给定一个参数时,如果参数非空,则结果为成功,并且该文字字符串始终非空,因此始终为“true”。
为了便于阅读,我会更改很长的行
[ $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
Shell 算术非常能够自行评估整数条件。它很少需要太多的测试和/或外部作业。这个while
循环很好地复制了您的嵌套循环:
它不会打印那么多,当然,我没有写那么多,但是,例如将上限设置为 16 而不是上面写的 101 并且......
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
.它非常便携、快速且易于使用。
您的子 shell 问题将在大多数 shell 中发生,但它是通过远的,在贝壳中最尖锐bash
。我交替做
( [ "$div" -gt "$num" ] ) && ...
...以及我在上面以 101 上限在多个 shell 中编写的方式,并且dash
在没有子 shell 的情况下在 0.017 秒内完成,在使用子 shell 的情况下在 1.8 秒内完成。busybox
.149 和 2、zsh .149 和 4、bash
.35 和 6、以及ksh93
.149 和 .160。ksh93
不会像其他 shell 那样必须分叉子 shell。所以也许问题不在于子外壳,而在于壳。