1

In the same thread as this question, I am giving this another shot and ask SO to help address how I should take care of this problem. I'm writing a bash script which needs to perform the following:

  1. I have a circle in x and y with radius r.
  2. I specify resolution which is the distance between points I'm checking.
  3. I need to loop over x and y (from -r to r) and check if the current (x,y) is in the circle, but I loop over discrete i and j instead.
  4. Then i and j need to go from -r/resolution to +r/resolution.
  5. In the loop, what will need to happen is echo "some_text i*resolution j*resolution 15.95 cm" (note lack of $'s because I'm clueless). This output is what I'm really looking for.

My best shot so far:

r=40.5 resolution=2.5 end=$(echo "scale=0;$r/$resolution") | bc for (( i=-end; i<=end; i++ ));do for (( j=-end; j<=end; j++ ));do x=$(echo "scale=5;$i*$resolution") | bc y=$(echo "scale=5;$j*$resolution") | bc if (( x*x + y*y <= r*r ));then <-- No, r*r will not work echo "some_text i*resolution j*resolution 15.95 cm" fi done done 

I've had just about enough with bash and may look into ksh like was suggested by someone in my last question, but if anyone knows a proper way to execute this, please let me know! What ever the solution to this, it will set my future temperament towards bash scripting for sure.

9
  • Thanks for any help; I'll be back in the morning few hours to update and respond. Commented Dec 8, 2009 at 8:34
  • 1
    ksh ? please... that's going from bad to worse. My opinion is that you are using the wrong tool. a shell is supposed to be used to run programs, not to do math. Commented Dec 8, 2009 at 8:37
  • I've had project leads insist everything had to be done in the shell before, because 'nobody knew perl'. Sometimes, you've just gotta make it work with the constraints you've been given. Even if those constraints aren't sane. Commented Dec 8, 2009 at 8:43
  • 1
    On the other hand, if you are asked, for example, to produce code in assembler, that would appear as an insane constraint, but that could have a motivated background (integration with previous code, timing issues). It's insane because uncommon, very demanding, difficult to test, and hard to do, but it's not unreasonable or unmotivated in that context. Human factors do exist, I agree, and must be kept into strong consideration, but it's always a matter of balance. A good manager should know when to evolve the technology of his team, otherwise it will keep him stuck in old technology. Commented Dec 8, 2009 at 9:04
  • 1
    If folk are insisting you use shell to do maths, I'd dig out dc.sed and say "what do you mean, you don't know sed"? sed.sourceforge.net/grabbag/scripts/dc.sed Commented Dec 8, 2009 at 9:04

4 Answers 4

1

You may want to include the pipe into bc in the $()'s. Instead of.

end=$(echo "scale=0;$r/$resolution") | bc 

use

end=$(echo "scale=0;$r/$resolution" | bc) 

should help a bit.

EDIT And here's a solution.

r=40.5 resolution=2.5 end=$(echo "scale=0;$r/$resolution" | bc) for i in $(seq -${end} ${end}); do for j in $(seq -${end} ${end}); do x=$(echo "scale=5;$i*$resolution" | bc) y=$(echo "scale=5;$j*$resolution" | bc) check=$(echo "($x^2+$y^2)<=$r^2" | bc) if [ ${check} -eq '1' ]; then iRes=$(echo "$i*$resolution" | bc) jRes=$(echo "$j*$resolution" | bc) echo "some_text $iRes $jRes 15.95 cm" fi done done 
Sign up to request clarification or add additional context in comments.

4 Comments

Adam, the final echo prints nothing but literally "some_text iresolution jresolution 15.95 cm"!
Correction added, though you may want to change the scale for the iRes / jRes equations depending on your requirements.
Thanks. On my Mac the use of seq had to be replaced with x=-end;x<end kind of thing. Also, the if statement should have [[ ... ]] instead of single brackets.
On Macs (and other BSDs?) there's the jot command which can be used instead of seq. The argument syntax is a little different.
1

As already mentioned this problem is probably best solved using bc, awk, ksh or another scripting language.

Pure Bash. Simple problems which actually need floating point arithmetic sometimes can be transposed to some sort of fixed point arithmetic using only integers. The following solution simulates 2 decimal places after the decimal point. There is no need for pipes and external processes inside the loops if this precision is sufficient.

factor=100 # 2 digits after the decimal point r=4050 # the representation of 40.50 resolution=250 # the representation of 2.50 end=$(( (r/resolution)*factor )) # correct the result of the division for (( i=-end; i<=end; i+=factor )); do for (( j=-end; j<=end; j+=factor )); do x=$(( (i*resolution)/factor )) # correct the result of the division y=$(( (j*resolution)/factor )) # correct the result of the division if [ $(( x*x + y*y )) -le $(( r*r )) ] ;then # no correction needed echo "$x $y ... " fi done done echo -e "resolution = $((resolution/factor)).$((resolution%factor))" echo -e "r = $((r/factor)).$((r%factor))" 

1 Comment

The script I'm write actual relies on user specified units, so I suppose this actually could work quite well if I specify nanometers!
0

you haven't heard of (g)awk ??. then you should go learn about it. It will benefit you for the long run. Translation of your bash script to awk.

awk 'BEGIN{ r=40.5 resol=2.5 end = r/resol print end for (i=-end;i<=end;i++) { for( j=-end;j<=end;j++ ){ x=sprintf("%.5d",i*resol) y=sprintf("%.5d",j*resol) if ( x*x + y*y <= r*r ){ print ".......blah blah ......" } } } }' 

Comments

0

It's looking more like a bc script than a Bash one any way, so here goes:

#!/usr/bin/bc -q /* -q suppresses a welcome banner - GNU extension? */ r = 40.5 resolution = 2.5 scale = 0 end = r / resolution scale = 5 for ( i = -end; i <= end; i++ ) { /* moved x outside the j loop since it only changes with i */ x = i * resolution for ( j = -end; j <= end; j++ ) { y = j * resolution if ( x^2 * y^2 <= r^2 ) { /* the next few lines output on separate lines, the quote on a line by itself causes a newline to be created in the output numeric output includes newlines automatically you can comment this out and uncomment the print statement to use it which is a GNU extension */ /* */ "some_text " i * resolution j * resolution "15.95 cm " /* */ /* non-POSIX: print "some_text ", i * resolution, " ", j * resolution, " 15.95 cm\n" */ } } } quit 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.