У меня есть следующий рабочий код:
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
текст немного сложен для чтения, и это может показаться (неопытному глазу), как будто его тестируют, а не устанавливают, что и делает. Так что я попытался изменить &&
в if...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"
Есть ли какая-то четкость блока без медлительности?
Обновление (04.01.2015, 10:40 EST)
Отличная обратная связь! Я сейчас использую следующее. Другие отзывы ?
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
Майкл Даррант
источник
источник
Largest Prime= 100
на моем компьютере.number_under_test/2
а не доnumber_under_test-1
: ни один из коэффициентов числа n не больше n / 2, поэтому вы все равно найдете все факторы для не простых чисел, делая это. (Также, если вас интересует только проверка на простоту, было бы достаточно итерировать до sqrt (n), но Bash в любом случае не имеет встроенной функции для вычисления квадратных корней.)(number_under_test/2)+1
чтобы учесть это{}
не очень нужны послеthen
пункта , потому чтоthen
уже служит в качестве группировки оператора (наряду сelif
,else
илиfi
). На самом деле, в некоторых оболочках вы можете написать, например,for i in 1 2 3; { echo $i; }
безdo
илиdone
.Ответы:
Это потому, что вы каждый раз создаете суб-оболочку:
Просто удалите скобки
Если вы хотите сгруппировать команды, в текущей оболочке для этого есть синтаксис :
(конечная точка с запятой требуется, см. руководство )
Обратите внимание, что
[ is_prime ]
это не то же самое, что[ $is_prime == true ]
: вы могли бы написать это так же просто$is_prime
(без скобок), которое вызвало бы встроенную командуtrue
илиfalse
команду bash .[ is_prime ]
это тест с одним аргументом, строка «is_prime» - когда[
задан один аргумент, результатом является успех, если аргумент не пустой, и эта литеральная строка всегда непуста, следовательно, всегда «true».Для удобства чтения я бы поменял очень длинную строку
в
Не недооценивайте пробелы, чтобы улучшить ясность.
источник
largest_prime=$number_under_test
должна быть в тогдашней ветке (та же ошибка в оригинале)[
Вызывает программу с буквальным названием[
, в то время как[[
она реализована в оболочке - следовательно, это будет быстрее. Попробуйтеtime for ((i = 0; $i < 1000; i++)); do [ 1 ]; done
и сравните с[[
. Смотрите этот ТАК вопрос для получения дополнительной информации.[
, это встроенный. В командной строке введитеtype -a [
иhelp [
which [
все еще возвращается/usr/bin/[
. Я также только что понял, что подразумевал, что zsh был тем же самым; для меня это говорит мне, что это встроенный. Но тогда ... почему [[быстрее?command -v
- еще одна хорошаяwhich
альтернатива; Смотрите также здесь .Я думаю, вы слишком усердно работаете над своей функцией. Рассмотреть возможность:
Оболочечная арифметика довольно способна самостоятельно оценивать целочисленные условия. Это редко требует слишком много тестов и / или внешних заданий. Этот
while
цикл хорошо дублирует ваши вложенные циклы:Конечно, он печатает не так много, я не так много писал, но, например, установил потолок 16, а не 101, как написано выше, и ...
Это определенно делает работу. И для аппроксимации вашего результата требуется совсем немного:
Просто делаю это, а не
echo
и ...Это работает в
busybox
. Это очень портативный, быстрый и простой в использовании.Ваша проблема с подоболочками возникает в большинстве оболочек, но, безусловно , наиболее остро в
bash
оболочке. Я чередовал... и как я написал выше в нескольких оболочках для потолка 101 и
dash
сделал это без вложенной оболочки в 0,017 секунды и с вложенной оболочкой в 1,8 секунды.busybox
.149 и 2, зш .149 и 4,bash
.35 и 6, иksh93
в .149 и .160.ksh93
не разветвляется на подоболочки, как другие оболочки. Так что, возможно, проблема не столько в оболочке, сколько в оболочке .источник
[ "$((...))" -eq "$((...))" ]
над(( (...) == (...) ))
? Последний менее портативный?[ "$((...))" -eq "$((...)) ]
работает в оболочках, которым не требуется 15 секунд для запуска программы, а другой нет. Если преимущество одного над другим вообще сомнительно, то это может только дать преимущество первому, что означает, что никогда не будет веской причины для использования(( (...) == (...) ))
.(( ... ))
. Я польщен, но у меня нет таких подробных знаний. (Помните, я тот, кто только что спросил,(( ... ))
менее ли переносим.) Поэтому я действительно не могу понять ваш ответ. : - / Не могли бы вы быть немного более явным?"$((...))"
это POSIX-спецификация, а другое расширение оболочки. Оболочки POSIX вполне способны. Дажеdash
иposh
будет правильно обрабатывать отраслевые тесты, как"$((if_true ? (var=10) : (var=5) ))"
и всегда назначать$var
правильно.busybox
ломается там - это всегда уносит обе стороны независимо от российской$if_true
ценности.