How to format decimal number to display the preciding zero but not the trailing ones?

11,426

Solution 1

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.}

Solution 2

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
Share:
11,426

Related videos on Youtube

mareicha
Author by

mareicha

Updated on September 18, 2022

Comments

  • mareicha
    mareicha over 1 year

    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'`
    
    • Admin
      Admin about 9 years
      Use awk instead of bc.
    • Admin
      Admin about 9 years
      @StéphaneChazelas Unfortunately, I am not that experienced with regular expression and awk I think I will try the printf solution.
  • mareicha
    mareicha over 9 years
    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?
  • choroba
    choroba over 9 years
    @Vesnog: Do you really need it? I'd like the fixed-length filenames more.
  • choroba
    choroba about 9 years
    @Vesnog: Check the update.
  • mareicha
    mareicha about 9 years
    @choraba Okay thanks, I think I should get my hands on regexs ASAP.
  • choroba
    choroba about 9 years
    @Vesnog: There's no regex. It just replaces . at the beginning with 0..
  • mareicha
    mareicha about 9 years
    @StéphaneChazelas Can I use sed to achieve that effect? Like f=echo "scale=3; $S + $i * $df" | bc | sed -e 's/^\./0./;s/$^\/0/./'
  • choroba
    choroba about 9 years
    @Vesnog: Parameter substitution would be faster than sed. Also, the second substitution makes no sense (there can't be anything after the end of line).
  • mareicha
    mareicha about 9 years
    @choroba As I have said I am not familiar with regexs how can I have sed check if there is a trailing zero to remove it.