53
echo 3+3

How can I evaluate such expressions in Bash, in this case to 6?

P Varga
  • 19,174
  • 12
  • 70
  • 108
hhh
  • 50,788
  • 62
  • 179
  • 282

9 Answers9

110
echo $(( 3+3 ))
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
37

expr is the standard way, but it only handles integers.

bash has a couple of extensions, which only handle integers as well:

$((3+3))  returns 6
((3+3))   used in conditionals, returns 0 for true (non-zero) and 1 for false
let 3+3   same as (( ))

let and (( )) can be used to assign values, e.g.

let a=3+3
((a=3+3))

for floating point you can use bc

echo 3+3 | bc

Dan Andreatta
  • 3,611
  • 1
  • 22
  • 15
  • expr not only handle integer, following expr just working. expr \( "0.5" \< 20 \), this expression can be use as if condition directly. – zw963 Oct 14 '18 at 03:52
  • `$(( ))` is every bit as standard as `expr` is -- having been specified by POSIX.2 since its initial publication in the early 90s -- and much faster to execute. By contrast, `let` is only present in bash for backwards compatibility with 1980s-era ksh. (By contrast, `(( ))` _without the leading `$`_ is a bash extension). – Charles Duffy Aug 12 '22 at 20:16
  • @zw963, POSIX doesn't require expr to support anything but integers. See https://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html -- any kind of floating-support your copy of `expr` may provide is a nonstandard extension. – Charles Duffy Aug 12 '22 at 20:17
24

in shells such as zsh/ksh, you can use floats for maths. If you need more maths power, use tools like bc/awk/dc

eg

var=$(echo "scale=2;3.4+43.1" | bc)
var=$(awk 'BEGIN{print 3.4*43.1}')

looking at what you are trying to do

awk '{printf "%.2f\n",$0/59.5}' ball_dropping_times >bull_velocities
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
11

You can make use of the expr command as:

expr 3 + 3

To store the result into a variable you can do:

sum=$(expr 3 + 3)

or

sum=`expr 3 + 3`
David
  • 134
  • 1
  • 10
codaddict
  • 445,704
  • 82
  • 492
  • 529
  • I'd like to add (since this post is apparently for Unix beginners) that the backticks on the last line are so the shell evaluates `epr 3 + 3` before sum gets assigned. – Mark Peschel Apr 26 '17 at 20:23
  • `expr` is an artifact of the 1970s. Ever since the early-90s publication of POSIX.2, shells have been required to support `sum=$((3 + 3))`, which is far more efficient. – Charles Duffy Aug 12 '22 at 20:16
3

Lots of ways - most portable is to use the expr command:

expr 3 + 3
2

I believe the ((3+3)) method is the most rapid as it's interpreted by the shell rather than an external binary. time a large loop using all suggested methods for the most efficient.

The HCD
  • 492
  • 8
  • 18
  • *nix processes are designed to be extremely lightweight and quick for exactly this reason. So using external binaries is not really that slow considering overall script performance of common usages. – hellodanylo May 26 '14 at 08:23
  • @hellodanylo it's still an orders-of-magnitude difference. `fork()`+`execve()` is cheaper on UNIX than Windows, sure, but it's still vastly slower than doing operations in the process that's already running. People causally doing expensive things is part of why "overall script performance" is widely considered to be unacceptably slow. – Charles Duffy Aug 13 '22 at 14:29
1

Solved thanks to Dennis, an example of BC-use:

$ cat calc_velo.sh

#!/bin/bash

for i in `cat ball_dropping_times`
do
echo "scale=20; $i / 59.5" | bc 
done > ball_velocities
hhh
  • 50,788
  • 62
  • 179
  • 282
  • put this into your question. also, you can just use one awk command. It parses files, and takes care of decimal maths. see my answer. – ghostdog74 Mar 31 '10 at 11:01
  • 1
    You're using the redirect operator `>` which truncates (overwrites) the destination file each time. Change that to the append operator `>>` or put the redirection after the `done` instead of after the `bc` like this: `done > ball_velocities`. – Dennis Williamson Mar 31 '10 at 13:18
1

One use case that might be useful in this regard is, if one of your operand itself is a bash command then try this.

echo $(( `date +%s\`+10 )) or even echo $(( `date +%s\`+(60*60) ))

In my case I was trying to get Unixtime 10 seconds and hour later than current time respectively.

codarrior
  • 524
  • 5
  • 5
0

My understanding of math processing involves floating point processing.

Using bashj (https://sourceforge.net/projects/bashj/) you can call a java method (with floating point processing, cos(), sin(), log(), exp()...) using simply

bashj +eval "3+3"
bashj +eval "3.5*5.5"

or in a bashj script, java calls of this kind:

#!/usr/bin/bashj
EXPR="3.0*6.0"
echo $EXPR "=" u.doubleEval($EXPR)

FUNCTIONX="3*x*x+cos(x)+1"
X=3.0
FX=u.doubleEval($FUNCTIONX,$X)
echo "x="$X " => f(x)=" $FUNCTIONX "=" $FX

Note the interesting speed : ~ 10 msec per call (the answer is provided by a JVM server).

Note also that u.doubleEval(1/2) will provide 0.5 (floating point) instead of 0 (integer)

Fil
  • 27
  • 4