131

I'm using a serial terminal to provide input into our lab experiment. I found that using

$ echo "5X5"

just returns a string of "5X5". Is there a command to execute a multiplication operation?

mmal
  • 179
  • 1
  • 9
bouncingHippo
  • 5,940
  • 21
  • 67
  • 107

8 Answers8

234

Yes, you can use bash's built-in Arithmetic Expansion $(( )) to do some simple maths

$ echo "$((5 * 5))"
25

Check the Shell Arithmetic section in the Bash Reference Manual for a complete list of operators.

For sake of completeness, as other pointed out, if you need arbitrary precision, bc or dc would be better.

KurzedMetal
  • 12,540
  • 6
  • 39
  • 65
49

For more advanced and precise math consider using bc(1).

echo "3 * 2.19" | bc -l 
6.57
tvm
  • 3,263
  • 27
  • 37
22

Internal Methods

Bash supports arithmetic expansion with $(( expression )). For example:

$ echo $(( 5 * 5 ))
25

External Methods

A number of utilities provide arithmetic, including bc and expr.

$ echo '5 * 5' | /usr/bin/bc
25

$ /usr/bin/expr 5 \* 5
25
Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199
18

The classical solution is:

 expr 5 \* 5

expr will only work with integer operands. Another nice option is:

 echo 5 5\*p | dc

dc can be made to work with non-integer operands.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • 1
    `dc` works with floats. Try `echo '4 k 50 7 / p' | dc`. The output is `7.1428`. The `k` command sets the precision. – Dennis Williamson Jun 15 '12 at 00:58
  • @Dennis In two different implementations of dc, I am seeing float operations work without assigning via `k`. I certainly remember the default precision being 0 (truncation to integer). Am I mis-remembering, or is it simply that newer implementations have changed behavior? – William Pursell Jun 15 '12 at 01:32
  • I have only used `dc` rarely over the years since I'm more algebraic and less RPN so I don't remember. On a GNU system I'm using, the default is 0. An old (1993) FreeBSD [`man` page](http://www.freebsd.org/cgi/man.cgi?query=dc&apropos=0&sektion=0&manpath=FreeBSD+1.0-RELEASE&arch=default&format=html) mentions the default being zero, but older BSD [`man` pages](http://www.freebsd.org/cgi/man.cgi?query=dc&apropos=0&sektion=0&manpath=2.9.1+BSD&arch=default&format=html) don't. – Dennis Williamson Jun 15 '12 at 01:51
  • By the way (for future readers), my example should have shown non-integer *operands* instead of only a non-integer result in order to accurately counter the assertion. Never fear, `echo '4 k 50.5 7 / p' | dc` works (output: `7.2142`). – Dennis Williamson Jun 15 '12 at 01:54
9

A simple shell function (no sed needed) should do the trick of interpreting '5X5'

$ calc() { bc -l <<< ${*//[xX]/*}; }
$ calc 5X5
25
$ calc 5x5
25
$ calc '5*5'
25
ikaerom
  • 538
  • 5
  • 27
  • 1
    Note that -- as described in https://wiki.bash-hackers.org/scripting/obsolete -- the `function` keyword is a ksh-ism; the POSIX sh standard doesn't specify it, so the more portable way to write that would be `calc() { ...; }`. Also, using `$@` in a context that evaluates to a single string is a bit weird; consider `$*` in scenarios where you aren't expanding to an array (or otherwise multiple words). – Charles Duffy Nov 07 '22 at 15:51
  • Thanks for improving the quality of this answer, @Charles Duffy. I've amended my answer with your input. – ikaerom Nov 07 '22 at 22:32
7

I use this function which uses bc and thus supports floating point calculations:

c () { 
    local a
    (( $# > 0 )) && a="$@" || read -r -p "calc: " a
    bc -l <<< "$a"
}

Example:

$ c '5*5'
25
$ c 5/5
1.00000000000000000000
$ c 3.4/7.9
.43037974683544303797

Bash's arithmetic expansion doesn't support floats (but Korn shell and zsh do).

Example:

$ ksh -c 'echo "$((3.0 / 4))"'
0.75
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
4

I have a simple script I use for this:

me@mycomputer:~$ cat /usr/local/bin/c

#!/bin/sh

echo "$*" | sed 's/x/\*/g' | bc -l

It changes x to * since * is a special character in the shell. Use it as follows:

  • c 5x5
  • c 5-4.2 + 1
  • c '(5 + 5) * 30' (you still have to use quotes if the expression contains any parentheses).
We Are All Monica
  • 13,000
  • 8
  • 46
  • 72
  • I like your idea to use an "x" for multiplication. You could similarly use square brackets instead of parentheses to avoid the need for quoting. `tr` can be used to do character mapping for multiple characters. – Dennis Williamson Apr 16 '14 at 19:58
3

If you like python and have an option to install a package, you can use this utility that I made.

# install pythonp
python -m pip install pythonp

pythonp "5*5"
25

pythonp "1 / (1+math.exp(0.5))"
0.3775406687981454

# define a custom function and pass it to another higher-order function
pythonp "n=10;functools.reduce(lambda x,y:x*y, range(1,n+1))"     
3628800