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>
bash
In bash
, that's probably as good as it gets. That uses a shell builtin. If you need the result in a variable, you could use command substitution, or the bash
specific (though now also supported by zsh
):
printf -v int %.0f "$float"
You could do:
float=1.23
int=${float%.*}
But that would remove the fractional part instead of giving you the nearest integer and that wouldn't work for values of $float
like 1.2e9
or .12
for instance.
Also note the possible limitations due to the internal representation of floats:
$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560
You do get an integer, but chances are that you won't be able to use that integer anywhere.
Also, as noted by @BinaryZebra, in several printf
implementations (bash, ksh93, yash, not GNU, zsh, dash), it is affected by the locale (the decimal separator which can be .
or ,
).
So, if your floats are always expressed with the period as the decimal separator and you want it to be treated as such by printf
regardless of the locale of the user invoking your script, you'd need to fix the locale to C:
LC_ALL=C printf '%.0f' "$float"
With yash
, you can also do:
printf '%.0f' "$(($float))"
(see below).
POSIX
printf "%.0f\n" 1.1
is not POSIX as %f
is not required to be supported by POSIX.
POSIXly, you can do:
f2i() {
awk 'BEGIN{for (i=1; i<ARGC;i++)
printf "%.0f\n", ARGV[i]}' "$@"
}
That one is not affected by the locale (the comma cannot be a decimal separator in awk
since it's already a special character in the syntax there (print 1,2
, same as print 1, 2
to pass two arguments to print
)
zsh
In zsh
(which supports floating point arithmetic (decimal separator is always the period)), you have the rint()
math function to give you the nearest integer as a float (like in C
) and int()
to give you an integer from a float (like in awk
). So you can do:
$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123
Or:
$ integer i=$((rint(5.678e2)))
$ echo $i
568
However note that while double
s can represent very large numbers, integers are much more limited.
$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808
ksh93
ksh93 was the first Bourne-like shell to support floating point arithmetic. ksh93 optimises command substitution by not using a pipe or forking when the commands are only builtin commands. So
i=$(printf '%.0f' "$f")
doesn't fork. Or even better:
i=${ printf '%.0f' "$f"; }
which doesn't fork either but also doesn't go all the trouble of creating a fake subshell environment.
You can also do:
i=$((rint(f)))
But beware of:
$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19
You could also do:
integer i=$((rint(f)))
But like for zsh
:
$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808
Beware that ksh93
floating point arithmetic honour the decimal separator setting in the locale (even though ,
is otherwise a math operator ($((1,2))
would be 6/5 in a French/German... locale, and the same as $((1, 2))
, that is 2 in an English locale).
yash
yash also supports floating point arithmetic but doesn't have math functions like ksh93
/zsh
's rint()
. You can convert a number to integer though by using the binary or operator for instance (also works in zsh
but not in ksh93
). Note however that it truncates the decimal part, it doesn't give you the nearest integer:
$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19 | 0))"
-9223372036854775808
yash
honours the locale's decimal separator on output, but not for the floating point literal constants in its arithmetic expressions, which can cause surprises:
$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator
It's good in a way in that you can use floating point constants in your scripts that use the period and not have to worry that it will stop working in other locales, but still be able to deal with the numbers as expressed by the user as long as you remember to do:
var=$((10.3)) # and not var=10.3
... "$((a + 0.1))" # and not "$(($a + 0.1))".
printf '%.0f\n' "$((10.3))" # and not printf '%.0f\n' 10.3
Best Answer
You can use
bc
features for that: