4

I have an expression "5+50*3/20 + (19*2)/7" I need to round it up to 3 decimal places. The answer to this is 17.92857142857143. When I use the script below it is giving me 17.928. The answer should be 17.929.

read exp
echo "scale=3; $exp" |bc -l

And one more question is how to use printf to do the same task

WannaBeCoder
  • 225
  • 1
  • 3
  • 10
  • You mean "round up" to three decimals. Depending on the rounding conventions applied, 17.928 may or may not be correct. – muru Dec 08 '14 at 14:51
  • Yes round it up. – WannaBeCoder Dec 08 '14 at 14:52
  • 1
    Don't try to do it in bash, use python or something else. At any rate, see: http://askubuntu.com/questions/179898/how-to-round-decimals-using-bc-in-bash – muru Dec 08 '14 at 14:54
  • 1
    echo $(printf "%.3f\n" $(echo " scale=4; $exp" |bc)) I used this and got the ans. But will see any one comes up with alternate method. I am learning bash so using it. – WannaBeCoder Dec 08 '14 at 14:59

4 Answers4

8

Just write this:

read exp
printf %.3f $(echo "$exp" | bc -l)
Amit24x7
  • 666
  • 1
    Please elaborate your answer for the benefit of other users. – countermode Feb 28 '17 at 09:38
  • 1
    $(command) is 'command substitution', it runs the command, captures its output and inserts it into the command line that contains the $(…) bc -l is calculating the expression and giving the result upto 20 decimal places printf %.3f is taking floating number where .3 tells it to round the number to 3 decimal places. – Amit24x7 Feb 28 '17 at 13:33
4

You can simplify the expression from your comment by using "here string" end removing both echos:

 printf "%.3f\n" "$(bc -l <<< "$var")"

or even

 printf "%.3f\n" "$(bc -l <<< "5+50*3/20 + (19*2)/7")"
jimmij
  • 47,140
  • Are the quotes around $(...) and $var necessary? It seems to work without the quotes, so I was wondering if they are there for some other cases. – Rahul Mar 25 '15 at 16:59
  • 1
    @Rahul Yes, it works here with or without quotes, but I recommend to always quote variables, command substitutions, arithmetic expansion, etc. unless you really know what you are doing. Read about details here: http://unix.stackexchange.com/questions/171346/security-implications-of-forgetting-to-quote-a-variable-in-bash-posix-shells – jimmij Mar 25 '15 at 18:48
1

Python seems have your preferred behaviour:

$ echo 'print(round(' "5+50*3/20 + (19*2)/7" ', 3))' | python3
17.929
muru
  • 72,889
  • Seems contrived to me to call a whole programming language to perform a single-line operation. Especially since there are solutions to this using purely bash. Why add such a dependancy, essentially for formatting?

    What if the os doesn't have python3? What if the interpreter would be call by python (as is the case on some distribution)? Older distribution? Does that work on Windows?

    – Francky_V Nov 13 '20 at 17:22
  • 1
    Nobody's posted a pure bash answer yet, though. I don't see it is all that different from calling bc. If anything, Python is more likely to be available than bc these days, and likely to be already loading into memory for some other program too, so it's probably faster to launch than bc. – muru Nov 13 '20 at 17:45
  • You're correct it is not pure bash.

    Still, IMO the point stands, I don't think it's a good practice. The path to the python interpreter may very well change from OS to os even on unix-base systems, not to mention windows.

    If that's going to be solution, then pretty much anything you can do in bash, you can do with nicer syntax in python, so why bother with bash at all, save for #!/bin/bash python [path-to-myscript.py]...

    – Francky_V Nov 13 '20 at 17:53
0

Assuming that the variable $exp gets the value 17.92857142857143 in your shell script, use the following line to round and print it:

python2 -c 'print round('$exp',3)'

muru
  • 72,889
Sreeraj
  • 5,062
  • As for the other - answer using python... Calling on such a dependancy for as one-liner that can definitely be done in multiple ways in bash is beyond me.... – Francky_V Nov 13 '20 at 17:25