[plt-dev] Inexact integers

From: Jos Koot (jos.koot at telefonica.net)
Date: Tue May 25 13:59:33 EDT 2010

My 2 cents,
The word 'real' means quite another thing in mathematics than in a
programming language. That may be unlucky, but as a programmer you soon find
out the distinction. Whatever presentation you select, all machine
presentable numbers are exact, in principle. We adorn a number with the
predicate 'inexact' if it was fed into the program as inexact (for example a
datum retrieved from inexact measurements) or if it is the result of a
function (such as log) that can at best produce an (internally exact) value
close the exact value. In PLT Scheme, now Racket, all reals are rationals.
This is a reasonable choice, I think. But let's not forget that it is
possible to represent sets of numbers that in meaning (not in cardinality,
for each representation is necessarily countably finite and in practice even
finite) may be approximations of irrational numbers. It is possible to
represents sets of numbers that include non rational reals (in mathematical
sense), for example by representing a number by a sign followed by a finite
list of exponents of the prime factors of the square of the number (as can
be useful in group theory) Also notice that number like pi gamma and e can
be represented exactly (just by their names) In general computations with
these numbers cannot be exact, although I can imagine a system in which
(expt e (* 2 pi)) -> the exact integer 1 and (log e) -> exact 1.

I can think of three reasons of adorning the representation of a number with
the predicate inexact:
1: it was produced by a function that cannot compute the exact value in the
any available representation within finite memory.
2: it was entered in the program as an approximation (for example a
3: There is an approximate inexact representation that allows enough
precision but enhances speed by using floating point hardware.

In Scheme a predicate either returns #f or #t. For me it would be acceptable
to have a third truth value #?. Thus, as far as I am concerned, (= 1.0 1.0)
might return #?. IIRC in R6RS the condition
(let ((x (lambda () '()))) (equal? x x)) -> #t has been dropped.
Nevertheless I would like to maintain this condition for numbers:
(let* ((x any-expression-producing-a-number) (y x)) (= x y)) -> #t

I must say I am rather satisfied with the two (exact and inexact) towers of
numeric types in PLT/Racket. It gives you choice between exactness against
speed. Furthermore, I think that a programmer who implements arithmetic
algorithms may be asked to know what he or she is doing.


-----Original Message-----
From: plt-dev-bounces at list.cs.brown.edu
[mailto:plt-dev-bounces at list.cs.brown.edu] On Behalf Of Joe Marshall
Sent: 25 May 2010 18:35
To: Michael Sperber
Cc: plt-dev at list.cs.brown.edu
Subject: Re: [plt-dev] Inexact integers

On Tue, May 25, 2010 at 7:23 AM, Michael Sperber
<sperber at deinprogramm.de> wrote:
> There was also the idea that an inexact number may denote an interval -
> and that IEEE floating-point is an implementation of that idea.  I think
> this doesn't make sense:

It doesn't make sense at all, and it would be nice if most programmers
understood this.

> Of course, it's possible to view an IEEE number
> as denoting the interval between the IEEE number just before it and the
> one after it.

Not easily.  The problem is that there are a lot of numbers that are on
asymmetric intervals.  1 and 2 come to mind (but not 3).  You would like it
to be the case that  1+1 = 2 and 1+2 = 3, but because the intervals aren't
symmetric, you won't find a consistent definition of addition that causes
both of those to be true.  (You could define addition as a lookup table
with 2^52 entries, of course, but it wouldn't be the kind of addition that
normal people talk about.)

> However, the IEEE operations aren't defined in terms of
> those intervals: they are defined (simplifying somewhat) as operations
> on "exact" numbers followed by rounding.

Followed by rounding *if necessary*.  And it often isn't necessary.
Many so-called rounding errors come from the translation from base 10
input to base 2, or from base 2 to base 10 on printing.  The computation
itself can often proceed without rounding.  For example, integer arithmetic
for add, subtract, and multiply are *exact* for floating-point integer
in the range -2^52 to 2^52.  There will be *no* rounding whatsoever.

Floating point isn't `magic' or a `black art', it's just a little trickier
rationals, and maybe on par with complex numbers.

  For list-related administrative tasks:

Posted on the dev mailing list.