1

I try to perform this simple calculation, but the programm always gives me incorrect results. If I use only integers, then I get 96

var=$(((100/24)*24))

even if I try to use bc:

var=$(bc <<< "scale=100;100/24*24")

I get something like this: 99.99999999999999999999999999999999999999999999999999999999999999999 99999999999999999999999999999999984;

How to let make the program count the correct way? So that I could get the same values as from the calculator?

Johny
  • 39
  • 1
  • 5
  • 1
    This is the result of rounding, to integers (bash) and floating point (bc). See [this SO question](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) for related information and links. – Jeff Bowman Aug 12 '15 at 16:44
  • 1
    So how can I solve this? I know that floats are always messed up, but how can I achieve the desired result? – Johny Aug 12 '15 at 16:48
  • 1
    Perhaps `(( var = 100 * 24 / 24 ))`? – twalberg Aug 12 '15 at 18:10
  • *Any* language that works with floating-point values will have this problem, because `100/24` cannot be represented exactly. To guarantee that `a/b*b == a` exactly, you need support for rational arithmetic. – chepner Aug 12 '15 at 18:17

1 Answers1

1

This is the result of rounding, to integers (100/24 -> 4 in bash) and floating point (bc lacks a "round" function). See this SO question for related information and links.

It's very hard to provide a general solution here: Most solutions depend on your exact use case, which is probably not what you posted in your question (otherwise you could just put var=100 and move on).

  • One technique is to reorder the problem (var=$((24*100/24))), which would keep all operations integers.
  • Another is to multiply by a large offset (var_millionths=$((1000000*(100/24)*24))) and divide out as needed, which would keep enough precision that Bash could round the result well.
  • Finally, you could (ab)use printf to perform the rounding step for you, because you want the number to be round in base 10 (i.e. when printed):

    printf "%.0f\n" $(BC_LINE_LENGTH=0 bc <<< "scale=100;100/24*24")
    
Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Is it possible to make it transform to float, when the number is should not be rounded? For example: `100/24*5=20.8333333333` – Johny Aug 12 '15 at 17:18
  • Not purely in Bash arithmetic. [Bash arithmetic operates only on fixed-width integers.](http://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html) – Jeff Bowman Aug 12 '15 at 17:25
  • Generally speaking, if the problem is complicated enough to need floating point math, it's probably outside of Bash's forte. Consider rewriting to Python or some other lightweight scripting language with floating-point primitives. – Jeff Bowman Aug 12 '15 at 17:27