views:

177

answers:

12

As (hopefully) most of you know, floating point arithmetic is different from real number arithmetic. It's for starters imprecise. Many numbers, especially decimals (0.1, 0.3) cannot be represented, leading to problems like this. A more thorough list can be found here.

Are there any general purpose languages that have built-in support for something closer to real number arithmetic? If not, what are good libraries that support this?

EDIT: Arbitrary precision decimal datatypes are not what I am looking for. I want to be able to represent numbers like 1/3, sqrt(3), or 1 + 2i as well.

+2  A: 

Though I hate to say it, Fortran. It has extensive support for arbitrary-precision arithmetic and tons of support for big-number calculations. It's ancient and gross, but it gets the job done.

Reinderien
If you can find a compiler for one of the more recent Fortran standard revisions, it isn't all *that* gross.
T.E.D.
@T.E.D. - Lots of compilers on the market have most; and a few (their number increasing) have all F2003 features. I don't find that "ancient" at all (in comparison with a lot of other languages-compilers/interpreters for them). And yes, it has extensive support for ... many things. One however, if one wants "gross" can always use FORTRAN 66 features only :-)
Rook
This may launch a flamewar, but Fortran77 is actually the surest thing. You write short and efficient routines with it, and then you call them with an honest language with the same ease as C functions. This is not true with F90 or the non-existent-in-practice F2003 (is this the one with OO features ?)
Alexandre C.
@Alexandre C. - I'm not sure as to what exactly you're reffering, but if one wants to use arbitrary precision (portable), then he will need f90/95 features/compiler (selected_real_kind() and co.). Could you elaborate on your comment however just in case I misunderstood its meaning? Also on the "non-existent-in-practice f2003" part?
Rook
@Rook: Do f90 and f95 really have support for sqrt(3) and the like? Or 1/3? It's been a very long time since I last used Fortran, and that was f77.
David Thornley
@David Thornley - Your question is somewhat vague. Yes, you can square an integer, but I don't think that's what you're asking. Take some google->fortran tutorial and read a little on KIND and data types. It should clear some dilemmas. I could write on it here, but that would just be rewriting the already written, and probably for worse. There have been some significant changes to the language in that segment since f77, yes.
Rook
A: 

Java: java.math.BigDecimal

C#: decimal

Thomas Mueller
My answer was before the question was edited.
Thomas Mueller
A: 

A lot of languages have support for that: Java has BigDecimal, Perl has Math::BigFloat and Math::BigRat, Haskell has Integer and a lot of libraries and languages are listed in the wikipedia.

musiKk
Ruby also has a `BigDecimal` class.
tcrosley
A: 

Ada natively supports fixed-point math as well as floating-point. Fixed-point can be much more exact than floating-point, as long as the number's exponents remain in range.

If you need floating-points, but more precision than IEEE gives, there are bignum packages around for just about every language.

I think that's about the best you can do. Neither scheme can exactly represent repeating decimals (like 1/3). It would probably be possible to come up with a scheme that does, but I know of no language that supports such a thing with a built-in type. Even that won't help you with irrational numbers (like pi and e). I believe there's even a theorem that says there will always be unrepresentable numbers, no matter what scheme you come up with.

T.E.D.
Whatever they are using, works: http://www.wolframalpha.com/index.html
NullUserException
OK, go use that to get an exact value for pi that I can use in my programs. I'll wait here. :-)
T.E.D.
@T.E.D Not saying they have the exact value, I am saying that's my definition of "good enough"
NullUserException
OK, there's the rub: What *exactly* is your defintion of "good enough"? I never really saw that defined, and 64-bit floats are more than good enough for almost everyone working outside of NASA. For everyone else, that's what bignum packages are for. Perfection, as mentioned in my answer, is not attainable in the general case,
T.E.D.
A: 

While its not "built-in", I think C++ (maybe C#) is your best bet. There are classes out there that have been written for this purpose.

http://www.oonumerics.org/oon/

Jess
The great majority of numerical libraries have been written for low-level languages such as C and Fortran, not high-level languages like C#.
Reinderien
You could certianly say it is *possible* to do in C++ and C# if you really want to, but "best bet"? Over languages with native support for such things? Hardly.
T.E.D.
Though, to play devil's advocate, C# does have built-in "decimal" for higher precision: http://msdn.microsoft.com/en-us/library/364x0z75%28VS.80%29.aspx
Reinderien
@Reinderien: It's very clear that what the OP wanted was not something like `long long double`, and I really doubt C# comes with infinite precision decimals.
David Thornley
+2  A: 

All the numbers used in your examples are algebraic numbers, and can be represented finitely as roots of polynomials with integer coefficients.

The same cannot be said of real numbers in general, which is easily seen when one considers that the reals are uncountable, but the set of computer programs is countable. Therefore most reals will not have a finite representation in code.

Jim Lewis
A: 

EDIT: Arbitrary precision decimal datatypes are not what I am looking for. I want to be able to represent numbers like 1/3, sqrt(3), or 1 + 2i as well.

Ruby has a Rational class, so 1/3 can be expressed exactly as Rational(1,3). It also has a Complex class.

tcrosley
There are other languages, like Lisp, with rationals and complex numbers. Having a non-numeric way to represent the square root of 3 is much less common.
David Thornley
+1  A: 

What you are looking for is symbolic calculation (MATLAB and other tools used in math and engineering are good at it).

If you want a general purposed language, I think expression tree in C# is good point to start with. In the essence, the ability to store the expression (instead of evaluate the expression into real values) is the key to be able to perform symbolic calculation. Note that expression tree does not provide symbolic calculation, it just provides the data structure that supports symbolic calculation.

Codism
A: 

To cover the real numbers with any flair you'll need a symbolic package.

Boost, the C++ project, has a Rational library, but that's only part of the story.

You have irrational numbers in all sorts of forms (pi, base of the natural logarithm, square and cube roots, the Champernowne constant, to name only a few). The only way I know of to handle arithmetic operations is a symbolic package with smarts as to the relationship amongst all of these numbers. Assuming you could express e^pi, how would you add one to it? Or take the square root of it?

Mathematica might handle these cases.

John at CashCommons
A: 

Scheme defines rationals, bignums, floating point and complex numbers. An implementation is not required to support them all, but if they are present, you can mix them and they will to "the right thing".

mfx
+1  A: 

This question is interesting, but raises some issues. First, you will never be able to represent all the real numbers using a (even theoretically infinite) computer, for cardinality reasons.

What you are looking for is a "symbolic numbers" datatype. You can imagine some sort of expression tree, with predefined constants, arithmetical operations, and perhaps algebraic (roots of polynomials) and transcendantal (exp, sin, cos, log, etc) functions.

Now the fun part of the story: you cannot find an algorithm which tells whether two such trees are representing the same number (or equivalently, which test whether such a tree is zero). I won't state anything precise, but as a hint, this is similar to the Halting Problem (for computer scientists) or the Gödel Incompleteness Theorem (for mathematicians).

This renders such a class pretty useless.

For some subfields of the reals, you have canonical forms, like a/b for the rationals, or finite algebraic extensions of the rationals (a/b + ic/d for complex rationals, a/b + sqrt(2) * a/b for Q[sqrt(2)], etc). These can be used to represent some particular sets of algebraic numbers.

In practice, this is the most complicated thing you will need. If you have a particular necessity, like ranges of floating point numbers (to prove some result is whithin a specified interval, this is probably the closest you can get to real numbers), or arbitrary precision numbers, you have freely available classes everywhere. Google boost::range for the former, and gmp for the latter.

Alexandre C.
+1  A: 

There are several languages with support for rational and complex numbers. Scheme, for instance, has support built in for arbitrarily precise rational numbers, and complex numbers with either rational, floating point, or integral coefficients:

> (+ 1/2 1/3)
5/6
> (* 3 1+1/2i)
3+3/2i
> (+ 1/2 .5)
1.0

If you want to go beyond rational numbers or complex numbers with rational coefficients, to algebraic numbers such as sqrt(2) or closed-form numbers like e, you will probably have to look beyond general purpose programming languages, and use a special purpose mathematical language like Mathematica or Maxima.

Brian Campbell