Let Bash do the math: Doing calculations using that bash

Have you ever wanted to “just do some math” without much fuss? I noticed a while ago (but haven’t really used it since) that bash (born again shell) has, amongst many other evaluations, an arithmetic one. Using the syntax $((expression)) you can evaluate the expression to arithmetically. Operations allowed are quite a few. From man bash:

ARITHMETIC EVALUATION
The shell allows arithmetic expressions to be evaluated, under certain circumstances (see the let and declare builtin commands and Arithmetic Expansion). Evaluation is done in fixed-width integers with no check for overflow, though division by 0 is trapped and flagged as an error. The operators and their precedence, asso ciativity, and values are the same as in the C language. The following list of operators is grouped into levels of equal-precedence operators. The levels are listed in order of decreasing precedence.

       id++ id--   variable post-increment and post-decrement
       ++id --id   variable pre-increment and pre-decrement
       - +             unary minus and plus
       ! ~             logical and bitwise negation
       **              exponentiation
       * / %         multiplication, division, remainder
       + -             addition, subtraction
       <>       left and right bitwise shifts
       =
                        comparison
       == !=       equality and inequality
       &               bitwise AND
       ^               bitwise exclusive OR
       |                bitwise OR
       &&             logical AND
       ||              logical OR
       expr?expr:expr
                        conditional operator
       = *= /= %= += -= <>= &= ^= |=
                        assignment
       expr1 , expr2
                        comma

Shell variables are allowed as operands; parameter expansion is performed before the expression is evaluated. Within an expression, shell variables may also be referenced by name without using the parameter expansion syntax. A shell variable that is null or unset evaluates to 0 when referenced by name without using the parameter expansion syntax. The value of a variable is evaluated as an arithmetic expression when it is ref erenced, or when a variable which has been given the integer attribute using declare -i is assigned a value. A null value evaluates to 0. A shell variable need not have its integer attribute turned on to be used in an expression.

Constants with a leading 0 are interpreted as octal numbers. A leading 0x or 0X denotes hexadecimal. Other wise, numbers take the form [base#]n, where base is a decimal number between 2 and 64 representing the arith metic base, and n is a number in that base. If base# is omitted, then base 10 is used. The digits greater than 9 are represented by the lowercase letters, the uppercase letters, @, and _, in that order. If base is less than or equal to 36, lowercase and uppercase letters may be used interchangeably to represent numbers between 10 and 35.

25 Comments

  1. Saturday, 18th Jun 2011 at 13:27

    Many thanks for this article. I would also like to say that it can be hard if you are in school and just starting out to create a long history of credit. There are many pupils who are only trying to make it and have a good or positive credit history is often a difficult point to have.

  2. jaenmedina said,

    Sunday, 27th Dec 2009 at 14:47

    If you want to evaluate multiple math expressions the parentheses must be escaped. This is necessary so the shell will not treat them as a reference to a sub-shell.
    For example, if you want to evaluate 100*(50-16), you will have to write 100*\(50-16\)

    Hope this helps.

    Source: Burtch, Ken. Linux Shell Scripting with BASH. Indianapolis, Indiana: Sams Publishing. 2004. Page 95

    • E.M. said,

      Sunday, 27th Dec 2009 at 14:55

      Really?

      ~$ echo $((5*(10+2)))
      60
      ~$ echo $((5*\(10+2\)))
      bash: 5*\(10+2\): syntax error: operand expected (error token is “\(10+2\)”)

      • jaenmedina said,

        Thursday, 31st Dec 2009 at 20:09

        If you see my example I did not use “$”

        • jaenmedina said,

          Thursday, 31st Dec 2009 at 20:40

          Besides, what you’re doing with that is creating a subshell.
          Subshells have the disadvantage of using more system resources. It would be more efficient tu run that same operation in the current shell.

  3. Tuesday, 20th Oct 2009 at 15:12

    […] operatori supportati sono molti, elencati anche in questo blog, ad esempio ** per calcolare la […]

  4. ken said,

    Thursday, 20th Aug 2009 at 16:02

    Why doesn’t this increment?

    ( i=0; while [ $i!=5 ]; do echo Increment: $((++${i})) ; done )

    • ken said,

      Thursday, 20th Aug 2009 at 17:07

      Figured it out… it should be

      ( i=0; while [ $i -ne 5 ]; do echo Increment: $((++i)) ; done )

  5. Juan said,

    Tuesday, 25th Nov 2008 at 17:35

    where i can find some how to related with advanced operations in bash?

  6. sysblog said,

    Wednesday, 13th Aug 2008 at 21:02

    as far as I know bash itself only knows about integers. But there’s an article that could help you at cool solutions on novell.com that uses bc and a small script.

    Cheers.

  7. julien said,

    Wednesday, 13th Aug 2008 at 18:22

    How does it work with decimal number??????
    I always get some errors.

  8. suma valluru said,

    Wednesday, 12th Sep 2007 at 12:57

    hi, arithmetic math is the perfect one in all the math topics…

    Cheers,
    Suma valluru
    —————————
    http://www.esumz.com

  9. sysblog said,

    Monday, 3rd Sep 2007 at 16:26

    Thanks, katm.

    But be warned that every single grouping has to come in double brackets. So for something like (3+4)*3 it’s $(($((3+4))*3)). So for some complex mathematics it would even be easier to use lisp 😀 But I like the quick and dirty $((2**32)) for 2^{32} for example.

    Cheers.

    • E.M. said,

      Monday, 9th Mar 2009 at 13:44

      No, it doesn’t.

      ~$ echo $(((3+4)*3))
      21

      • sysblog said,

        Monday, 9th Mar 2009 at 20:39

        Thanks for sharing that information! I cannot remember where I had my info from but maybe it just was due to a different version of bash.

        • E.M. said,

          Monday, 9th Mar 2009 at 23:00

          Your way will work, but it just looks more complicated.

          Basically, your way is saying ‘do 3+4, then use this like a variable, times this variable by 3 then make it act like another variable’.

          Where as my way basically does it all in one go.

          It probably doesn’t make much difference either way, but it’s just easier to read IMO 🙂

  10. katm said,

    Monday, 3rd Sep 2007 at 16:06

    Oh now this is just nifty.

    And as a Linux noob, I think even I can follow it.

    Just another toy to play with 🙂


Leave a comment