2

Is there a possible workaround to Julia's floating point and rounding arithmetic wherein it outputs even a simple value such as 1.6 to be 1.6000000000000012

Since I intend to use Julia to prove the degree of exactness of a quadrature method, I need to eventually show that the computed value of an integral equals its exact value, but due to these discrepancies in the trailing decimals in some cases, I am unable to do so.

stark
  • 2,246
  • 2
  • 23
  • 35
  • 4
    See http://stackoverflow.com/questions/588004/is-floating-point-math-broken?rq=1 – Asik Apr 04 '16 at 19:45
  • 1
    Did you consider [BigFloat](http://docs.julialang.org/en/release-0.4/stdlib/numbers/#Base.BigFloat)? – Philip Apr 04 '16 at 19:45
  • @Philip : No, I haven't, but wouldn't the same discrepancy creep up in BigFloat as well, the only difference would be the position of the erroneous decimal right ? – stark Apr 04 '16 at 19:50
  • I'm not sure what you mean by discrepancy. If you mean "I typed 1.6 but I got something not exactly 1.6" then check out the link; you'll see that you may prefer to initialize the number manually, i.e. you can get as close to exactly 1.6 as you please. If you mean "as I do floating point arithmetic small errors will accrue"--well, that's exactly why one should use an arbitrary-precision floating point number and think carefully through its use to keep those errors within tolerable bounds :). – Philip Apr 04 '16 at 19:53
  • 1
    If *any* inexactness at all, even within an arbitrarily tight boundary, is intolerable, then you need [exact arithmetic](http://stackoverflow.com/questions/30264742/exact-decimal-arithmetic-in-julia) – Philip Apr 04 '16 at 19:58
  • 1
    See also http://stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represented-exactly-in-binary – mtrw Apr 04 '16 at 21:11
  • 2
    @stark, just curious if you've found something different in any other language you've used? If so, it's likely that the language is just hiding the extra decimal points from you. (An exception might (or might not) be Mathematica, which I believe makes extensive use of Rational numbers.) – kmsquire Apr 06 '16 at 16:00

3 Answers3

8

In Julia you can use Rational types to represent rational numbers without losing precision. See the docs here. However, you will still need to be very careful with your computations not to promote Rational to Real.

Your example of 1.6 could be represented as follows:

> x = 16//10
8//5

Julia would then remember the denominator and numerator and store the value as such. You could use these rational numbers to compare your derived value to the true value.

If at the end you need to convert back to floating point numbers (because for example your result was irrational) than you can use the BigFloat type to get higher precision. Rational numbers would give you precision improvement even when using BigFloats:

> @printf "%.100f" BigFloat(1.6 - 1.5)
0.1000000000000000888178419700125232338905334472656250000000000000000000000000000000000000000000000000

> @printf "%.100f" BigFloat(16//10 - 15//10)
0.1000000000000000000000000000000000000000000000000000000000000000000000000000002159042138773611156347
Julia Learner
  • 2,754
  • 15
  • 35
niczky12
  • 4,953
  • 1
  • 24
  • 34
7

Posting comment as an answer...see Exact decimal arithmetic in Julia and likely use one of BigFloat or Rational; use the former if you just need your floats to have precision to "at least N decimal places" where N is up to you; use the latter if an arbitrarily and boundedly small error still breaks what you're doing.

If you use BigFloat, you'll probably want to manually initialize your literal values:

Note that because decimal literals are converted to floating point numbers when parsed, BigFloat(2.1) may not yield what you expect. You may instead prefer to initialize constants from strings via parse(), or using the big string literal.

julia> BigFloat(2.1) 2.100000000000000088817841970012523233890533447265625000000000000000000000000000

julia> big"2.1" 2.099999999999999999999999999999999999999999999999999999999999999999999999999986

Community
  • 1
  • 1
Philip
  • 7,253
  • 3
  • 23
  • 31
3

This is an artifact of the fact that floating-point numbers are stored as a fixed, finite number of bits (32 or 64 typically), which cannot represent any arbitrary quantity with infinite precision. In particular, because they use a base 2 representation, a quantity that can be represented exactly in base 10 (such as 1.6) may not be exactly representable in base 2 and vice-versa. You'll have to take this finite precision into account in your proof.

I have no experience with julia specifically, but typically there are more than 1 numeric type available for a programming language. Perhaps there exists an arbitrary-precision floating point library you can use.

Asik
  • 21,506
  • 6
  • 72
  • 131