3

I have the following script on Ubuntu 14.04.1 LTS 64-bit bash command prompt:

S=0.030
F=0.150
N=10
reso=20
DIFF=`echo "scale=3; $F - $S" | bc -l`
df=`echo "scale=3; $DIFF / $N" | bc -l`
is=`echo "scale=3; $S / $df" | bc -l`
if=`echo "scale=3; $F / $df" | bc -l`
cd wgdisp-out
for i in `seq 0 $N` 
    do
        f=`echo "scale=3; $S + $i * $df" | bc -l | awk ' sub("\\.*0+$","") '`
        #h5totxt hsli0$f.h5 | harminv -vt 0.1 -w 2-3 -a 0.9 -f 200 | sed -n '/^[[:digit:]]/p' | cut -d , -f 1
        echo $f
    done

I would like to have f displayed as 0.03, 0.042, 0.054, .... 0.138, 0.15 and this is critical since f is used inside file names such as hsli0.03.h5. Can someone point me in the right direction? I am not pretty familiar with arithmetic in shell.

EDIT: I tried the following construct, but it does not yield the desired output; furthermore the scale option for bc does not seem to work.

f=`echo "scale=3; $S + $i * $df" | bc | sed -e 's/^\./0./' -e 's/$^\/0/./'`

EDIT2: Got it working with the following single command:

f=`echo "scale=3; $S + $i * $df" | bc | sed -e 's/^\./0./;s/[0]*$//g'`
  • 1
    Use awk instead of bc. – Stéphane Chazelas Feb 20 '15 at 11:20
  • @StéphaneChazelas Unfortunately, I am not that experienced with regular expression and awk I think I will try the printf solution. – Vesnog Feb 20 '15 at 11:22
2

Floating point arithmetic support in bash is very poor. You can still use printf, though:

printf '%5.3f\n' $f
printf '%.3g\n' $f

If you just want to prepend 0 to ., you can use parameter expansion:

f=${f/#./0.}
# if negative numbers are possible, too
f=${f/#-./-0.}
  • Well I somehow managed to have the leading zero printed but now I would like to get rid of the trailing zeros is it possible with this construct? – Vesnog Feb 20 '15 at 11:12
  • @Vesnog: Do you really need it? I'd like the fixed-length filenames more. – choroba Feb 20 '15 at 11:16
  • I really need it since generating those files took around 3 hours and I do not have that much time right now. So for now I should go with it in Matlab there was the format specifier %g which takes care of the trailing zeros, do we have it in this printf implementation too? – Vesnog Feb 20 '15 at 11:17
  • @Vesnog: Check the update. – choroba Feb 20 '15 at 11:19
  • @choraba Okay thanks, I think I should get my hands on regexs ASAP. – Vesnog Feb 20 '15 at 11:22
3

In bc, scale is a special variable that is used to limit the scale (the number of digits after the comma) of the result of some operators like / (division). It is not the precision in numbers displayed by bc, it's used in computation.

For instance, in scale=1; 1/3, the result is 0.3 (3/10), which is quite far from 1/3.

You should use large scale values for your computation, and only reduce scale for display (by instance, by dividing by 1 in the end).

Compare:

$ echo "scale=100; r=1/3*300; scale=3; r/1" | bc
99.999

with:

$ echo "scale=3; 1/3*300" | bc
99.900

I'd write it:

n=10
echo "
  s = 0.030
  f = 0.150
  n = $n
  r = 20
  scale = 100
  d = (f - s) / n
  scale = 3
  for (i = s; i <= f; i += d) i/1" |
    bc |
    sed 's/^\./0./;s/0*$//' |
    while read f; do
      h5totxt "hsli$f.h5" | harminv -vt 0.1 -w 2-3 -a 0.9 -f 200
    done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.