Doing simple math on the command line using bash functions: $1 divided by $2 (using bc perhaps)

69,157

Solution 1

I have a handy bash function called calc:

calc () {
    bc -l <<< "$@"
}

Example usage:

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

You can change this to suit yourself. For example:

divide() {
    bc -l <<< "$1/$2"
}

Note: <<< is a here string which is fed into the stdin of bc. You don't need to invoke echo.

Solution 2

Bash can do the math itself to some extent. It's not useful for accuracy, though, as it rounds.

[user]$ echo $(( 10/5 ))
2

But you're exactly right - a bash function would be a simple shortcut and your example basically works.

divide() {
  echo "scale=25;$1/$2" | bc
}

Throw that in your .bashrc and then you can:

[user]$ divide 10 5
2.0000000000000000000000000

Solution 3

You probably know the bash builtin 'expr' as in

$ expr 60 / 5
12

which is limited to integers and needs the spaces between the arguments.

What is keeping you from defining a function along the lines of the echo expression you're already using? I.e.

 divide () {
   echo $1/$2 | bc
 }

Solution 4

Not really an answer to this precise question, but it might be good to know. Use zsh ;-)

% echo $((65320./670))
97.492537313432834

Solution 5

A dirty hack for small values and a limited precision without using bc would be, to multiply the nominator before division, to get an accurate result.

Example without precision:

echo $((13/7)) 
1

and with 2 digits precision: multiply by 100 and move the decimal point 2 steps to the left:

echo $((100*13/7)) | sed 's/..$/.&/'
1.85
echo $((100*13/7))%
185%

This is only useful if the range of numbers is known before, and the precision is always the same. Avoiding to call bc, and calling sed seems not very reasonable.

Note, that multiplying the values might lead to overflow errors, but not very early:

echo $((1000000000*12345678901))
-6101065172709551616
Share:
69,157

Related videos on Youtube

Matthew
Author by

Matthew

Updated on September 18, 2022

Comments

  • Matthew
    Matthew almost 2 years

    Sometimes I need to divide one number by another. It would be great if I could just define a bash function for this. So far, I am forced to use expressions like

    echo 'scale=25;65320/670' | bc
    

    but it would be great if I could define a .bashrc function that looked like

    divide () {
      bc -d $1 / $2
    }
    
  • Matthew
    Matthew over 12 years
    hmm... couldn't find any debian package for 'calc'
  • Peter.O
    Peter.O over 12 years
    The package is called apcalc (Arbitary Precision)... The binary is called calc
  • Admin
    Admin over 12 years
    @Peter.O Ok, in the Arch Linux repos it's called calc.
  • Aska Ray
    Aska Ray over 12 years
    I agree it's looking better without the additional echo thrown in, but since it's a shell builtin, it comes with little to no additional cost. What keeps me from using '<<<' in shell functions is its limitation to bash, while the additional echo allows using it in the original bourne shell or ksh without changes.
  • user unknown
    user unknown over 12 years
    echo $((10 / 5)) needs no quotation.
  • Matthew
    Matthew over 12 years
    just ignorance. i didn't realize i could make it work that way...
  • laebshade
    laebshade over 12 years
    Using double parentheses to evaluate math expressions is deprecated. Use: $[expression] instead
  • user unknown
    user unknown over 12 years
    @laebshade: I can prove you wrong, the opposite is true. Here is a citation of the bash manual: The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
  • Sridhar Sarnobat
    Sridhar Sarnobat over 8 years
    Significant annoyance: echo $((6383/7671)) will give you zero. You need to be explicit about floating point numbers: echo $((6383.0/7671.0))
  • Kusalananda
    Kusalananda about 7 years
    @TatjanaHeuser ksh, the 93-variant, supports here-strings.
  • thebiggestlebowski
    thebiggestlebowski over 6 years
    To assign to a variable, I did this: foo=$(bc -l <<< "( 2 * 5 ) + 5")
  • G-Man Says 'Reinstate Monica'
    G-Man Says 'Reinstate Monica' almost 5 years
    Also discussed here, here and here.