And when I say bash math, I do not mean being mean to math, and I do not mean math as it is done in bash. I mean math as humans do it, but on the bash command line.
I would like to see a set of bash commands that do basic math, so one can do the basic math at the command line without invoking a calculator OR sending data clumsily to a program. Such as: add, which will return the sum of whatever numbers separated by white space (or expressions that can be evaluated to a number) it gets. Similarly, divide (takes two values) and multiply (takes two values). Don’t forget squareroot. One command in this toolkit could be simply the command math that takes sequences of numbers or expressions and operators and returns the closest thing to a result possible.
Software needed: Nifty bash math tools
Comments

#1 Eric Lund November 6, 2009
The expr command already does this. For instance, if I type
> expr 1 + 1
I get the result 2.It’s available in both bash and tcsh.

#3 Greg Laden November 6, 2009
Eric,
2 + 3 – 1/4 does not equal 5. Expr says it does.
Liam: That is a very good example of why my utility is needed!

#4 Dave X November 6, 2009
Try this (notwelltested) function definition in Bash:
$ math(){
echo “scale 10; $*”bc
}$ math 1+2 + 1/4
3.2500000000
$ 
#5 rpsms November 6, 2009
bash is restricted to integer math AFAIK, so you would just need to put a wrapper around Liam’s code.
Probably this is also why eric’s example returns 5. It’s rounding up 4.75 to an integer.

#6 rpenner November 6, 2009
And “bc l” would mean for many cases you could skip the “scale=10;” part.
bc l loads a “math library” of function defined in bc’s own scripting language.
Then a(1)*4 is pi. Want more digits (like 200), then you need scale=200.
$ echo ‘scale=200;a(1)*4′  bc l
3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
223172535940812848111745028410270193852110555964462294895493038196 
#7 Dave X November 6, 2009
@rpenner: ooh, thst’s better.
math(){ echo “$MATHOPTIONS;$*”bc l; }
PI=`math “a(1)*4″`
echo $PI
math $PI*4^2
Greg, what do you expect from ‘divide 1 3′ or ‘math 1/3’?
Greg, what would you want this to return:
$ divide 1 3

#8 Greg Laden November 6, 2009
I would expect “This number can not be computed to the final digit. This is not logical. I am melting down” and then smoke to start coming from behind the monitor.
Or, “0.33333”

#9 Dave X November 6, 2009
I don’t know the linux command for smoke, but defining the above wrapper function in your .bashrc should give you some of what you seek.

#10 peter November 6, 2009
if you’re not a bash purist,
function add {
python c “print $1 + $2
}
function divide {
perl e “print $1/$2″
}
etc. etc… 
#11 rpsms November 6, 2009
operators: + – / x
usage: foo.sh + 2 2 2 2 2 2 2
error checking: nope#!/bin/bash
set f
expression=$@
math_op=$1expression=${expression//”${math_op}” /}
if [ “$math_op” = “x” ]; then
math_op=”*”
fiexpression=${expression// /”${math_op}”}
echo “scale=10; ${expression}”  bc
set +f 
#12 Greg Laden November 6, 2009
Isn’t perl math better than bc math?

#13 Jeff November 6, 2009
Lifehacker just had a post on this topic: http://lifehacker.com/5396183/createanawesomecommandlinecalculator
The short answer: put this command in your .bashrc (or .bash_profile) file: calc(){ awk “BEGIN{ print $* }” ;}
Then you can use: “calc 99*3/5″ to get 59.4

#14 Greg Laden November 6, 2009
sweet. very very sweet.

#15 gruebait November 6, 2009
I find Python convenient for a bunch of calculations I frequently need to do. I just put a file, mymod.py in […]/sitepackages. It imports a bunch of functions from math, and includes some functions I wrote for things I often do. I just fire up Python and do a ‘from mymod import *’.
Instant personalized math from the CLI. Of course, it’s not really bash…

#17 Ivan November 7, 2009
calc() { echo $@  tr x '*'  bc l; }
The l option of bc is easier than setting the scale variable, and tr allows the use of x for multiplication.
qsum() { sed 's/^[ \t]*//;s/[ \t].*//'  grep .  \ tr  _  sed '2,$s/$/+/;$s/$/p/'  dc; }
This one adds up a column of numbers specified on stdin. It assumes that the first word on each line is a number, and trims away any other data on each line.

#18 Ivan November 7, 2009
Oh, and for serious computation (but still quick inandout from the shell), use PARI/GP. Invoke at the commandline with
gp q
(q suppresses the welcome banner). Loads faster than you can blink, and does some serious shit– number theory, numerical integration, power series, special functions– all to arbitrary precision. Documentation includes a PDF reference card so you can quickly get into it.

#19 Greg Laden November 7, 2009
rpenner[6]: Then I should define bc as a shortcut to bc l c
Ivan, nice
As far as bash purity goes, all of the standard scripting languages are part of bash if they take one liners. That is not impure, it is very pure as part of the bash philosophy. As long as there is a healthy range of widely used and well maintained scripting languages (which currently means sed, awk, perl, python for sure) there is no pressure to add every single bell and whistle to bash. Break it down to small problems, solve one problem at at a time, do it well.

#20 Peter November 7, 2009
Let’s not forget R:
You can do oneliners like this:
alias mult= ‘Rscript e “prod( as.double( commandArgs( TRUE ) ) )”‘OR this one:
alias calc=’Rscript e “eval( parse( text=commandArgs( TRUE ) ) )”‘[note: I’ve added some spaces to the above code to help it render more suitably in browsers with large font — gtl]

#21 Peter November 7, 2009
@Greg
Thanks for fixing the spacing.I discovered a slight problem with the version of ‘calc’ that I gave above– it can be a bit tempermental about spaces. Here’s an improved version that should fix that problem and also remove the [1] at the beginning of the output:
$ alias calc=’Rscript e “cat( file=stdout(), eval( parse( text=paste( commandArgs(TRUE), collapse=\”\”))))”‘

#22 Ralf Muschall November 7, 2009
You might try zsh, it has floats (and a somewhat strange idea what characters a word consists of, unless you clear $WORDCHARS).