1

This question already has an answer here:

Let's say I have a variable and I want to print 5 significant digits after I multiplied it by 1000. zsh can do it:

zsh$ x=2.8026407e+00
zsh$ printf "%.5g\n" "$(( 1000*${x} ))"
zsh> 2802.6

Can bash do it as well?

bash$ x=2.8026407e+00
bash$ printf "%.5g\n" "$(( 1000*${x} ))"
bash> bash: 1000*2.8026407e+00 : syntax error: invalid arithmetic operator (error token is ".8026407e+00 ")

I think there is no way to make native bash understand floating point operations, is there? I know I can use e.g. awk, but I was wondering if bash could do this at all or not.

(I'm not surprised that bash cannot handle floats, but that zsh can!)

marked as duplicate by Jeff Schaller, user88036, muru, αғsнιη, Romeo Ninov Oct 9 '18 at 4:34

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

3

bash does not do floating-point arithmetic, but rather fixed-point, where the decimal is fixed at zero places (i. e. integer maths). This means that you can work around it for some very very basic computation:

$ a=1;b=3
$ echo $(( (a*1000 / b ) ))
333

So, 1/3 to three places is .333.

This is a bad idea; don't do this.

There are many ways to do FP maths on the command line. Here are just two examples:

$ python -c 'print( 1.0 / 3 )'
0.333333333333
$ echo 'scale=3; 1.0/3' | bc
.333
2

bash cannot do decimal point mathematical operations, only integer operations

robert@pip2:/tmp$ echo $((2 * 3))
6
robert@pip2:/tmp$ echo $((2 * 3.5))
bash: 2 * 3.5: syntax error: invalid arithmetic operator (error token is ".5")
robert@pip2:/tmp$ 
2

Yes, like dash, bash is limited to integer arithmetic math in $((…)).
In fact, by default, all shells (default POSIX) will print 37 with this:

$ echo "$((1000/27))"
37

From [POSIX][1]:

Only signed long integer arithmetic is required.

You need to change the numbers a bit to get floating point math in ksh, zsh, and yash (not jsh, dash, ash, lksh, mksh and bash):

$ echo $((1000/27.0))
37.037037037037037

But be careful with zsh precedence and precision:

$ for sh in ksh yash zsh; do $sh -c 'printf "%20d\n" "$(( 1<<63 - 5))"'; done
  288230376151711744
  288230376151711744
 9223372036854775803

$ for sh in ksh yash zsh; do $sh -c 'printf "%-20s\n" "$((1/10.0))"'; done
0.1                 
0.1                 
0.10000000000000001

Unexpected zsh truncation limits:

$ zsh -c 'echo $((12345678901234567890));echo $((12345678901234567890123))'

zsh:1: number truncated after 19 digits: 12345678901234567890
1234567890123456789

zsh:1: number truncated after 22 digits: 12345678901234567890123
-1363962815083169260

There is a workaround in bash using printf capabilities (limited to ~10 digits):

$ bash -c 'printf "%.10f\n" "$(( 10**10*  1000/27  ))e-10"'
37.0370370370

But why bother having bc available:

$ echo '1000/27' | bc -l
37.03703703703703703703

[1]: Only signed long integer arithmetic is required.

1

Not using bash specifically, but you should have bc available to you:

# bc doesn't like exponential numbers in the manner provided.  It can be done, but this number is equivalent.
x=2.8026407
printf "1000 * %s" "$x" | bc

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