I have the following working code:
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"
This code runs quickly is 0.194 seconds. However I found the && is_prime= false a bit hard to read and it could look (to the untrained eye) as if it was being tested rather than being set which is what it does.
So I tried changed the && into an if...then and this works - but is 75 times slower at 14.48 seconds. It's most noticeable on the higher numbers.
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"
Is there any was to have the clarity of the block without the slowness?
Update (1/4/2015 10:40am EST)
Great feedback! I am now using the following. Any other feedback ?
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"
Largest Prime= 100on my computer. – Giulio Muscarello Jan 03 '15 at 18:09number_under_test/2instead of up tonumber_under_test-1: No factor of a number n is greater than n/2, so you will still find all factors for non-prime numbers by doing this. (Also if you were only interested in testing for primeness, it would be sufficient to iterate up to sqrt(n), but Bash doesn't have a built-in function to compute square roots anyway.) – Malte Skoruppa Jan 04 '15 at 00:42(number_under_test/2)+1to allow for that – Michael Durrant Jan 04 '15 at 14:36{}are not really needed after thethenclause because thethenalready serves as a grouping operator (along withelif,else, orfi). In fact, in some shells, you could write, for example,for i in 1 2 3; { echo $i; }with nodoordone. – Jonathan Leffler Jan 04 '15 at 15:27unset IFS.if $is_primewill fail unless$is_primeevals to a word. If it is split for any reason it will fail. You also have the problem of needing to generate your entire parameter set before you can do even a single calculation. It is very inefficient and the whole{1..100}block must reside in memory for the duration. – mikeserv Jan 04 '15 at 20:26if [ $remainder == 0 ]-- this is an arithmetic test, so use an arithmetic expression:if (( $remainder == 0 ))-- or remove the temp variable altogether:if (( $number_under_test % $divider == 0 )). You don't actually use the$separatorvariable anywhere – glenn jackman Jan 05 '15 at 14:35printfwithout a format specifier. If one of your variables happens to contain a%, you'll get an error. – glenn jackman Jan 05 '15 at 14:43(( $var ))is definitely not a safe thing to do. Rather(( var ))should be preferred. But((...))is probably not a good way to go, anyway. – mikeserv Jan 05 '15 at 17:10[ "$((...))" -ne 0 ]or evenmath() { return "$((!($*)))"; }but is far less portable. You might as well use syntax that will work everywhere rather limiting the application of what you do if the practical difference amounts only to typing a few characters. – mikeserv Jan 05 '15 at 17:44bashandzshat least even(( var ))is still an unsafe thing to do. I think both of those shells will still wind up evaling the contents as a math statement rather than an integer regardless of whether you$expandit first or not. You could explicitlytypesetit first, I suppose, to guard against that. But if you do so, then its contents are no longer questionable. – mikeserv Jan 05 '15 at 18:04