How to do integer & float calculations, in bash or other languages/frameworks?

555,434

Solution 1

There are lots of options!!!

Summary

$ printf %.10f\\n "$((10**9 * 20/7))e-9"   # many shells. Not mksh.
$ echo "$((20.0/7))"                       # (ksh93/zsh/yash, some bash)
$ awk "BEGIN {print (20+5)/2}"
$ zcalc
$ bc <<< 20+5/2
$ bc <<< "scale=4; (20+5)/2"
$ dc <<< "4 k 20 5 + 2 / p"
$ expr 20 + 5
$ calc 2 + 4
$ node -pe 20+5/2  # Uses the power of JavaScript, e.g. : node -pe 20+5/Math.PI
$ echo 20 5 2 / + p | dc 
$ echo 4 k 20 5 2 / + p | dc 
$ perl -E "say 20+5/2"
$ python -c "print(20+5/2)"
$ python -c "print(20+5/2.0)"
$ clisp -x "(+ 2 2)"
$ lua -e "print(20+5/2)"
$ php -r 'echo 20+5/2;'
$ ruby -e 'p 20+5/2'
$ ruby -e 'p 20+5/2.0'
$ guile -c '(display (+ 20 (/ 5 2)))'
$ guile -c '(display (+ 20 (/ 5 2.0)))'
$ slsh -e 'printf("%f",20+5/2)'
$ slsh -e 'printf("%f",20+5/2.0)'
$ tclsh <<< 'puts [expr 20+5/2]'
$ tclsh <<< 'puts [expr 20+5/2.0]'
$ sqlite3 <<< 'select 20+5/2;'
$ sqlite3 <<< 'select 20+5/2.0;'
$ echo 'select 1 + 1;' | sqlite3 
$ psql -tAc 'select 1+1'
$ R -q -e 'print(sd(rnorm(1000)))'
$ r -e 'cat(pi^2, "\n")'
$ r -e 'print(sum(1:100))'
$ smjs
$ jspl
$ gs -q  <<< "5 2 div 20 add  ="

Details

Shells

You can use POSIX arithmetic expansion for integer arithmetic echo "$((...))":

$ echo "$((20+5))"
25
$ echo "$((20+5/2))"
22

Quite portable (ash dash yash bash ksh93 lksh zsh):
Using printf ability to print floats we can extend most shells to do floating point math albeit with a limited range (no more than 10 digits):

$ printf %.10f\\n "$((1000000000 *   20/7  ))e-9"
2.8571428570

ksh93, yash and zsh do support floats here:

$ echo "$((1.2 / 3))"
0.4

only ksh93 (directly) and zsh loading library mathfunc here:

$ echo "$((4*atan(1)))"
3.14159265358979324

(zsh need to load zmodload zsh/mathfunc to get functions like atan ).


Interactively with zsh:

$ autoload zcalc
$ zcalc
1> PI/2
1.5708
2> cos($1)
6.12323e-17
3> :sci 12
6.12323399574e-17

With (t)csh (integer only):

% @ a=25 / 3; echo $a
8

In the rc shell family, akanga is the one with arithmetic expansion:

; echo $:25/3
8

POSIX toolchest

bc (see below for interactive mode), manual here

Mnemonic: best calculator (though the b is in fact for basic).

$ echo 20+5/2 | bc
22
$ echo 'scale=4;20+5/2' | bc
22.5000

(supports arbitrary precision numbers)


bc interactive mode:

$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
5+5
10

2.2+3.3
5.5

Rush's solution, expr (no interactive mode):

$ expr 20 + 5
25
$ expr 20 + 5 / 2
22

Joshua's solution: awk (no interactive mode):

$ calc() { awk "BEGIN{print $*}"; }
$ calc 1/3
0.333333

Other more or less portable tools

Arcege's solution, dc (interactive mode: dc):

Which is even more fun since it works by reverse polish notation.

$ echo 20 5 2 / + p | dc 
22
$ echo 4 k 20 5 2 / + p | dc 
22.5000

But not as practical unless you work with reverse polish notation a lot.

Note that dc predates bc and bc has been historically implemented as a wrapper around dc but dc was not standardised by POSIX


DQdims's calc (required sudo apt-get install apcalc):

$ calc 2 + 4
6

General purpose language interpreters:

manatwork's solution, node (interactive mode: node; output function not needed):

$ node -pe 20+5/2  # Uses the power of JavaScript, e.g. : node -pe 20+5/Math.PI
22.5

Perl (interactive mode: perl -de 1):

$ perl -E "say 20+5/2"
22.5

Python (interactive mode: python; output function not needed):

$ python -c "print(20+5/2)"
22 # 22.5 with python3
$ python -c "print(20+5/2.0)"
22.5

Also supports arbitrary precision numbers:

$ python -c 'print(2**1234)'
295811224608098629060044695716103590786339687135372992239556207050657350796238924261053837248378050186443647759070955993120820899330381760937027212482840944941362110665443775183495726811929203861182015218323892077355983393191208928867652655993602487903113708549402668624521100611794270340232766099317098048887493809023127398253860618772619035009883272941129544640111837184

If you have clisp installed, you can also use polish notation:

$ clisp -x "(+ 2 2)"

Marco's solution, lua (interactive mode: lua):

$ lua -e "print(20+5/2)"
22.5

PHP (interactive mode: php -a):

$ php -r 'echo 20+5/2;'
22.5

Ruby (interactive mode: irb; output function not needed):

$ ruby -e 'p 20+5/2'
22
$ ruby -e 'p 20+5/2.0'
22.5

Guile (interactive mode: guile):

$ guile -c '(display (+ 20 (/ 5 2)))'
45/2
$ guile -c '(display (+ 20 (/ 5 2.0)))'
22.5

S-Lang (interactive mode: slsh; output function not needed, just a ; terminator):

$ slsh -e 'printf("%f",20+5/2)'
22.000000
$ slsh -e 'printf("%f",20+5/2.0)'
22.500000

Tcl (interactive mode: tclsh; output function not needed, but expr is):

$ tclsh <<< 'puts [expr 20+5/2]'
22
$ tclsh <<< 'puts [expr 20+5/2.0]'
22.5

Javascript shells:

$ smjs
js> 25/3
8.333333333333334
js>

$ jspl
JSC: 25/3

RP: 8.33333333333333
RJS: [object Number]
JSC:
Good bye...

$ node
> 25/3
8.333333333333334
>

Various SQL's:

SQLite (interactive mode: sqlite3):

$ sqlite3 <<< 'select 20+5/2;'
22
$ sqlite3 <<< 'select 20+5/2.0;'
22.5

MySQL:

mysql -BNe 'select 1+1'

PostgreSQL:

psql -tAc 'select 1+1

_The options on mysql and postgres stop the 'ascii art' image !

Specialised math-oriented languages:

R in plain mode - lets generate 1000 Normal random numbers and get the standard deviation and print it

$ R -q -e 'print(sd(rnorm(1000)))'
> print(sd(rnorm(1000)))
[1] 1.031997

R using the littler script - lets print pi squared

$ r -e 'cat(pi^2, "\n")'
9.869604
$  r -e 'print(sum(1:100))'
[1] 5050

PARI/GP, an extensive computer algebra system for number theory, linear algebra, and many other things

$ echo "prime(1000)"|gp -q
7919                        // the 1000th prime
$ echo "factor(1000)" | gp -q
[2 3]
[5 3]                       // 2^3*5^3
$ echo "sum(x=1,5,x)" | gp -q
15                          // 1+2+3+4+5

GNU Octave (a high-level interpreted language, primarily intended for numerical computations)

Also supports complex numbers:

$ octave
>> 1.2 / 7
ans =  0.17143
>> sqrt(-1)
ans =  0 + 1i

Julia, high-performance language and interpreter for scientific and numerical computing.

Non-interactive option:

$ julia -E '2.5+3.7'
6.2

GhostScript GhostScript is a PostScript interpreter, very commonly installed even in very old distributions.
See PostScript docs for a list of supported math commands.

Interactive example:

$ GS_DEVICE=display gs
GPL Ghostscript 9.07 (2013-02-14)
Copyright (C) 2012 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
GS>5 2 div 20 add  =
22.5
GS>

Solution 2

There are many ways to calculate. For simple expressions you can use bash itself:

echo $((20+5))

or expr:

expr 20 + 5

And for complex cases there is great tool bc:

echo "20+5" | bc

Btw, bc can calculate even very complex expression with roots, logarithms, cos, sin and so on.

Solution 3

Nobody has mentioned awk yet?

Using POSIX shell functions, and awk math power, just define this (one line) function:

calc(){ awk "BEGIN { print $*}"; }

Then just execute things like calc 1+1 or calc 5/2

Note: To make the function always available, add it to ~/.bashrc (or your corresponding shell's startup file)

Of course, a little script named "calc" with the following contents:

#!/bin/sh -
awk "BEGIN { print $* }"

could also work.

Solution 4

The mentioned solutions are fine for very simple calculations, but very error-prone. Examples:

# without spaces expr 20+5 produces literally 20+5
expr 20+5
→ 20+5

# bc's result doesn't give the fractional part by default
bc <<< 9.0/2.0
→ 4

# expr does only integer
expr 9 / 2
→ 4

# same for POSIX arithmetic expansion
echo $((9/2))
→ 4

# bash arithmetic expansion chokes on floats
echo $((9.0/2.0))
→ bash: 9/2.0: syntax error: invalid arithmetic operator (error token is ".0")

# Most `expr` implementations also have problems with floats
expr 9.0 / 2.0
→ expr: non-integer argument

A syntax error like the last ones is easily noticed, but integer responses with a discarded float part can easily go unnoticed and lead to wrong results.

That's why I always use a scripting language like Lua for that. But you can choose any scripting language that you're familiar with. I just use Lua as an example. The advantages are

  • a familiar syntax
  • familiar functions
  • familiar caveats
  • flexible input
  • spaces usually don't matter
  • floating point output

Examples:

lua -e "print(9/2)"
→ 4.5

lua -e "print(9 / 2)"
→ 4.5

lua -e "print(9.0/2)"
→ 4.5

lua -e "print (9 /2.)"
→ 4.5

lua -e "print(math.sqrt(9))"
→ 3

Solution 5

You could use bc. E.g.,

$ echo "25 + 5" | bc
30

Alternatively bc <<< 25+5 will also work.

Or interactively, if you want to do more than just a single simple calculation:

$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
25 + 5
30

The GNU implementation of bc prints that header/copyright info on start-up when both its stdin and stdout go to a terminal. You can suppress it with the (GNU-specific) -q option. For more information see the bc man page

Share:
555,434
Michael Durrant
Author by

Michael Durrant

rails ruby rspec rock

Updated on September 18, 2022

Comments

  • Michael Durrant
    Michael Durrant almost 2 years

    Using echo "20+5" literally produces the text "20+5".

    What command can I use to get the numeric sum, 25 in this case?

    Also, what's the easiest way to do it just using bash for floating point? For example, echo $((3224/3807.0)) prints 0 :(.

    I am looking for answers using either the basic command shell ('command line') itself or through using languages that are available from the command line.

    • zinking
      zinking about 12 years
      I assume author is asking for bash command line, while answers all tend to diversify to all kinds of scripting languages.
    • aqwert
      aqwert about 12 years
      man bash → /expression
    • minorcaseDev
      minorcaseDev almost 10 years
      Teach bash integer division with floating point results: stackoverflow.com/a/24431665/3776858
    • RussellStewart
      RussellStewart almost 10 years
      I like to use pythonpy (github.com/russell91/pythonpy) for my calculator: py 3224/3807 => 0.846861045443. py 'math.factorial(4)' => 24.
    • Scott - Слава Україні
      Scott - Слава Україні over 9 years
    • Nikana Reklawyks
      Nikana Reklawyks over 8 years
    • ndemou
      ndemou almost 7 years
      I really don't like how this part of the question "...or other languages/frameworks?" opened the gates of hell to answers for all kind of languages/frameworks.
  • Michael Durrant
    Michael Durrant about 12 years
    and bc is interesting: whatis bc -> An arbitrary precision calculator language Interesting! Thanks!
  • Michael Durrant
    Michael Durrant about 12 years
    +1 for both pipe ("|") and interactive mode options for bs. Does one ctrl-d to exit?
  • Levon
    Levon about 12 years
    @MichaelDurrant Yes, ^D will do the trick as will quit
  • lgarzo
    lgarzo about 12 years
    @MichaelDurrant could you re-revise your edits, I must have rejected by mistake?
  • Michael Durrant
    Michael Durrant about 12 years
    added some bolding in. Looks ok
  • Michael Durrant
    Michael Durrant about 12 years
    I added your expr option to the accepted answer. Had to pick one to accept and centralize.
  • Arcege
    Arcege about 12 years
    There is also dc, which is even more fun since it works by reverse polish notation. echo 20 5 + p | dc But not as practical unless you work with reverse polish notation a lot.
  • Michael Durrant
    Michael Durrant about 12 years
    I also like the use of <<<, does this mean pipe it in AND execute the command?
  • lgarzo
    lgarzo about 12 years
    That is a Here String. (From the manual:) <<<word is expanded and supplied to the command on its standard input. Shorter than echo ... |.
  • manatwork
    manatwork about 12 years
    As seems you are collecting the alternatives in this answer, you may add node too: node -pe 20+5. This one benefits the power of JavaScript, for example: node -pe 20+5/Math.PI.
  • lgarzo
    lgarzo about 12 years
    @manatwork Added your solution.
  • manatwork
    manatwork about 12 years
    bc's result is not integer, just rounded to scale, who's default value is 0. So bc <<< 'scale=4;9.0/2.0' if you want the fractional part.
  • Marco
    Marco about 12 years
    Thanks for the correction. But still, it's error prone. Will I remeber to add scale if I use bc in a couple of weeks? Probably not. And even if there's a way to change it permanently, it will bite you if you're on a system with the default settings.
  • Peter.O
    Peter.O about 12 years
    You don't need to enter interactive mode, unless you particularly want to, eg: calc -e '2+4; 3+5; 3.4+5; 2^4 prints 4 output lines, or just calc -e 33+(3^3).. +1 I like the idea of using something called 'calc' for a calculator :)
  • user unknown
    user unknown about 12 years
    Just count bc as one of the scripting languages. I always know whether I need integer results or not - if integer is alright I stay in bash, else I rarely have reason to use bc. For lua, you have to remember -e, print and parenthesis.
  • Levon
    Levon about 12 years
    me too! Python is my swiss army knife
  • Peter.O
    Peter.O about 12 years
    I've just realized that the -e option is not needed when there is only one expression... neat!..
  • manatwork
    manatwork about 12 years
    Is that ghc meaning Glasgow Haskell Compiler?
  • David Andersson
    David Andersson about 12 years
    The perl -e "print x+y" produce ugly output. It should be perl -e 'print x+y,"\n"' but then the input becomes ugly instead.
  • lgarzo
    lgarzo about 12 years
    @DavidAndersson Well, I do not use perl (just looked up the reference), but you can make the input more crowded by using perl -e "use feature say; say 2+2". Or append a ; echo to the command, even an echo $(perl ...). Which do you think would suit best?
  • manatwork
    manatwork about 12 years
    @lgarzo, perl -E 'say 2+2'.
  • Arcege
    Arcege about 12 years
    I always have one window in screen just running Python.
  • manatwork
    manatwork about 12 years
    @lgarzo, @MichaelDurrant, I made some changes: 1) Unified the examples: kept old expression for tools unknown by me; kept original 20+5 expression where floating point is not supported; added 20+5/2 expression; where 20+5/2 produces integer/rounded result, added floating point alternative. 2) As the question was tagged interactive, added information about how to start the tool in interactive mode. 3) If expressions' result are automatically displayed in interactive mode (ex: 20+5 vs. print 20+5), added the note “output function not needed”). Hope you also find it cleaner now.
  • lgarzo
    lgarzo about 12 years
    @manatwork Thanks for your thorough editing! Now it really makes sense.
  • manatwork
    manatwork about 12 years
    Some minor details worth to mention: 1) from dual is needed by Oracle, MySQL is able to select without from clause. 2) PostgreSQL not requires the alias. 3) The ; is only required by SQLite. 4) MySQL and PostgreSQL will work only if they are able to connect to a database server. 5) MySQL and PostgreSQL will draw ASCII-art table around the results. To get only the value: mysql -BNe 'select 1+1' and psql -tAc 'select 1+1.
  • gokhan acar
    gokhan acar about 12 years
    As a variation on the bc approach, I added the following function (that I found on stackexchange somewhere) to my .bashrc file. I can just enter calc 2+3 and get 5. ## Command line calculator calc () { bc -l <<< "$@" }
  • gopi1410
    gopi1410 about 12 years
    holy crap! I doubt if there's anything more left!
  • rush
    rush about 12 years
    You're trying to execute expr 20+5. You need to type spaces between numbers and plus to make it work: expr 20 + 5. That's important.
  • Dalker
    Dalker about 11 years
    Just always use bc -l rather than plain bc, then never worry about scale.
  • Daniel
    Daniel over 10 years
    my hat is off to you
  • CMCDragonkai
    CMCDragonkai about 10 years
    Wow this is the best, even supports floats. It works without installing anything!
  • Hastur
    Hastur about 10 years
    @gopi1410 There is,[there is...(unix.stackexchange.com/a/136507/6638.8). To Michael I cannot resist the temptation to answer even if you just edit... :-) Sorry
  • RussellStewart
    RussellStewart almost 10 years
    pythonpy (github.com/russell91/pythonpy) is a nice way to do this and other things in python syntax without having to fire up an interactive shell: py '3.2 * 5' => 16
  • Gavin S. Yancey
    Gavin S. Yancey over 9 years
    wouldn't print(eval(' '.join(sys.argv[1:]))) do the same thing?
  • user2820379
    user2820379 over 9 years
    If I would have enough reputation I would vote this down because it includes many commands which will not produce what we can say would be the expected output. Some will not even work at all (see answers below).
  • Paul Tobias
    Paul Tobias over 8 years
    Very nice, I wanted to have a floating comparison, here is how I did it with your help: a=0; b=0.0; if echo "$a" "$b" | awk '{ exit ($1 == $2) ? 0 : 1 }'; then echo 'equals'; else echo 'not equals'; fi
  • Daniel Alder
    Daniel Alder over 7 years
    echo "$((20.0/7))" fails in bash and dash
  • Sergio Abreu
    Sergio Abreu over 7 years
    sugest you removing bc without scale configuration as bc without scaling doesn't perform division correctly (it rounds floor), so bc <<< 20+5/2 = fail
  • ndemou
    ndemou almost 7 years
    I don't like the emphasis on what other answers got wrong. When looking for answers I personally expect the answer first.
  • ndemou
    ndemou almost 7 years
    You're using a hammer to hit a fly here
  • Random832
    Random832 almost 7 years
    @ndemou It's installed by default on some distributions... and a lot of these other answers aren't. And did you really need to comment that on an answer that's five years old?
  • ndemou
    ndemou almost 7 years
    I think it's good to comment when I down-vote and it is a practice that's also encouraged by S.E. I don't see why five years are relevant. The same comment applies to all similar answers -- nothing personal. (BTW even the most obscure program can be be installed by default on some distribution. In this case I've tested recent installations of Debian, Ubuntu, CentOS and RedHat and units is not)
  • Stéphane Chazelas
    Stéphane Chazelas almost 7 years
    awk will use your system's double floating point type, so is going to be as precise as most other tools that don't do arbitrary precision (note that gawk can do arbitrary precision). awk uses the OFMT variable to convert number to their string representation for output (%.6g by default, you may want to change that to %.17g is you want higher precision).
  • Stéphane Chazelas
    Stéphane Chazelas almost 7 years
    Note that fish's math is just a function that calls bc (though that's to change)
  • asmeurer
    asmeurer almost 7 years
    @ndemou I said "interactive" calculator. Although it's also worth noting that at some point if you are doing complex enough things in a script, sanity dictates you use something other than bash (like Python).
  • ipatch
    ipatch over 6 years
    @Stéphane Chazelas great answer! However I couldn't find a solution / answer for fish shell 🐠 🐚 => fishshell.com
  • Stéphane Chazelas
    Stéphane Chazelas over 6 years
    @Chris, fish is a moving target. They're working on their new math builtin (or whatever it's called now) as we speak. Feel free to edit. It's not my answer and it's community wiki.
  • ipatch
    ipatch over 6 years
    @StéphaneChazelas yeah doing a search on this page for fish got me to the right place. ;)
  • ndemou
    ndemou over 6 years
    Thanks Stéphane Chazelas -- I've updated my answer (math -s4 seems to be supported in older versions also)
  • ijoseph
    ijoseph almost 6 years
    c () { bc -l <<< "$@" } will define a function c for quick and easy use. e.g. c 3/2 will give you 1.50000000000000000000. The link in the above describing how to do that is dead.
  • Levon
    Levon almost 6 years
    @ijoseph not quite sure about the 'dead link' comment, the bc man page? Still works for me.
  • ijoseph
    ijoseph almost 6 years
    @Levon the man page link still works. However, the link: paweng.com/2008/08/15/unix-command-line-calculator , which you provide as the target of "This" in the sentence "This page also shows how to set up an alias…" appears dead.
  • Levon
    Levon almost 6 years
    @ijoseph Thanks .. I removed the reference to that 6 year old link (wish the links stood out more clearly on my browser - didn't even see it when I looked yesterday)
  • volvox
    volvox about 5 years
    Great post, but IMHO none of these are convenient in the 21st century. bc should default to scale=4 as a default.
  • Alberto Salvia Novella
    Alberto Salvia Novella about 4 years
    📦 As command: gitlab.com/es20490446e/calc
  • Alberto Salvia Novella
    Alberto Salvia Novella about 4 years
    Since all the solutions have notorious drawbacks, I have created a new command for this: unix.stackexchange.com/a/577257/223253
  • Alberto Salvia Novella
    Alberto Salvia Novella about 4 years
    @Jeff Schaller Don't delete post without any feedback.
  • 0andriy
    0andriy about 3 years
    Why are you using bashism in examples where it's not needed?
  • Admin
    Admin about 2 years
    @done The commands are not duplicates. Intentionally, there are two sequential commands of the same type to show the interger and decimal division. For example bc without -l and bc with scale (not the whole -l). Similar for the python commands, the first one is integer dividion by purpose.
  • Admin
    Admin about 2 years
    @thanasisp, though there's dc <<< "4 k 20 5 + 2 / p" and echo 4 k 20 5 2 / + p | dc, which are just two ways of doing the same thing (apart from the (20+5)/2 vs. 20+5/2 distinction). The former doesn't have the integer equivalent, and the other tools don't have the variants with echo, just the nonstandard here-string ones. The Python thing case might warrant a comment because of the Python 2 vs. 3 difference, and well, dc's k might warrant a note too, though since it's RPN, I guess it can just be left obscure too. (Also the dc <<< isn't mentioned in the longer descriptions.)
  • Admin
    Admin about 2 years
    (Saying that kinda makes me think I should go through the whole list, and besides it would be nice to have them all spell out the same expression... but I don't think I can be bothered right now. )
  • Admin
    Admin about 2 years
    @ilkkachu I rolled back last change for the reason I explain into my comment. For example, it modified the bc example for integer division to bc -l which is decimal. If you or anyone think of any improvement, please do it.
  • Admin
    Admin about 2 years
    @thanasisp, yes, and I'm saying not all of your arguments seem to apply, for the reasons I explained.