floor() function and mathematical integers

Dennis E. Hamilton orcmid at email.com
Thu May 17 03:28:47 EDT 2001


OK, we are standing in two different worlds here.  I am completely clear on
the implementation of floating-point arithmetic.  But floor is not defined,
for me, as an implementation, it is defined as a mathematical function.

The Standard C Library defines an implementation.  The definition I am
looking at is "The floor function returns the largest integral value not
greater than x, expressed as a double." (section 7.5.6.3, Returns)

This is a completely clear statement about the implementation of floor() in
the Standard C Library.  (Harbison and Steele add to this and say the result
is an exact mathematical integer.  I like that idea, of course, but their
statement isn't satisfied by 7.5.6.3 for me.)

If I had my druthers, I would have there be a domain-error exception for
floor(x) when x is outside the range for which consecutive integers are
exactly representable.  That is, I wouldn't deliver results outside the
domain where the mathematical definition of floor() can't be rigorously
honored.  Having this specified in the definition of the library would also
provide an important heads up that floor() is consistently implementable
only over a restricted domain of doubles, and that the implementation
enforces the restriction as a safeguard.

My concern is with the promise that we make in specifying the library.
Although the definition for the Standard C Library is accurate and precise
(though quite subtle), I am not sure that it serves users of Python.

Here's how far apart our perspectives are on this:

>> In particular, the Peano axioms fail with respect to arithmetic on
>> the ones that are too-much greater than 1.

>Only matters if you're adding 1.

It is the whole point of something being an integer that you can always add
1 and get the next greater integer.  When we aren't delivering on that, I
think it is very important to make it clear to people.  Raising a domain
error is an effective way to do that.  It is also consistent with Python's
producing an OverflowError for integer-range problems when other languages,
like C, require that users deal with the consequences of the implementation.
I don't think the design requirements for Python are the same as those that
applied when C Language was first defined.

By the way, I am not proposing any changes to Python.  I am not concerned
about that.  I am concerned about the low level of things in Python and
other languages, including Java and C# and the impact that has on users,
ones led to believe that they are dealing with something higher-level and
ones who will likely never consult the Standard C Library definition to get
the scoop.  These subtleties tend to be below the noise level around
programming languages and that allows for lots of misunderstandings and
wasted hours debugging.  I am looking for the lesson in this.

I was always pleased that C Language used "int" and "float" and "double,"
rather than "integer" and "real" as was done in Algol and Pascal.  It could
be viewed as a tip-off that these are types for implementations, and that
they are limited in various ways.  I don't know whether that was the
intention.  I admired the result.

I was wondering whether I could be satisfied by a version of floor() that
delivered a Python long integer.  It would certainly satisfy the requirement
of delivering an integer value.  Nope.  The domain restriction still seems
important, especially since the typical use of floor is on a calculated
intermediate result.  I think the rub for me is that floor() is a
number-theoretic function, in contrast with sqrt() or cos() where
approximations are understood differently (and cos(2.0**500) is still
problematic).

Thanks for this conversation.  It clarifies some things for me.  I think
when I want to offer implementations of mathematical objects, I will stick
to the pure stuff (bignums and rationals), and when offering popular
implementations (i.e., IEEE floats and 32-bit ints), I will keep them
distinct.  I can see the desirability of both.  I don't think one approach
alone will serve the needs of all users.  And users deserve to know more
clearly when they are relying on arithmetic schemes in which a large number
of compromises have been made and there are boundary cases to be careful
about.  I don't think that we do a very good job of letting people know when
things are not as simple as we encourage them to believe through our
omissions.

-- Dennis

-----Original Message-----
From: python-list-admin at python.org
[mailto:python-list-admin at python.org]On Behalf Of Tim Peters
Sent: Wednesday, May 16, 2001 18:41
To: Python-list
Subject: RE: floor() function and mathematical integers


[Dennis E. Hamilton]
[ ... ]
>
> Here's my hypothesis:  For the most part, we attribute integer-ness to
> the numerals themselves, rather than to the *structure* consisting of
> the objects and the operations over them.

There's no confusion about floating-point that can't be cured by study.  The
repeated confusions I've seen over the decades amount to no more than that:
people making bad assumptions about, and bringing fantasy expectations to, a
system they've never bothered to learn. "Being around" floating-point for
1000 years won't make up for the lack of a deliberate effort to learn.

<orcnote> Sorry.  I am talking about integers here, not floating-point.  But
I guess the bigger question is about who computers and languages like Python
are for.  My father built his own cars and was raised in an era when people
made and repaired their own bicycles, motorcycles, and small airplanes.  I
don't even change my own oil.  I could.  I don't.  I can't remember how long
it has been since I had to repair a flat.  I never learned to drive with a
standard transmission.  I have no problem getting into the bits and bytes,
obviously.  I grew up with them, the same way my dad grew up in the age of
the automobile.  I am concerned that we appeal to people's naive
understanding in our language and use of concepts and, when dissonance
arises, we tell them to RTFM (or in this case, master IEEE 754).  Maybe that
is the way it will have to be.  I just wonder if there isn't a smoother way.
</orcnote>

[ ... ]

> I am not arguing, here, whether floor(x) as a real function is ill-
> defined, though I think there is a case for that when x is a whole
> number but not "an integer."

I don't know what that means, unless you want floating-point operations to
raise exceptions whenever they have an input x such that x+1==x -- in which
case it's unrealistic.  If you want integers and only integers, don't use
fp.

<orcnote>  Well, unfortunately for floor(), the whole idea is to move from
non-integers to integers.  I must confess that in places where I care about
it, as in j = (L + R)/2, or c = (N + b - 1)/b, the definition of "/" on
positive-integer operands helps me out.  I am not expanding my concern to
floating-point operations that don't pretend to be number-theoretic.
</orcnote>

> I do claim that these over-sized floats are *not* integers in the
> sense that they do not honor the standard laws of arithmetic for
> integers in the available floating-point arithmetic system.

floor() does the best job it can given what it knows, which is its input.
If
I compute 2.0**500 in 754 arithmetic, I in fact get the exact answer, and
floor() of that has no business presuming "oh no, that's 'too big' to be an
exact answer -- so I'll help Tim by complaining instead".  If you're afraid
of inexact results, don't use fp at all, or use it with the inexact trap
enabled.
<orcnote>
I don't buy this example.  If you knew that is what you were doing, you
wouldn't need floor.  If you didn't know that was what you were doing, the
outcome is an accident.
</orcnote>

[ ... ]

> Am I making myself understood?  I am not looking for agreement,
> just whether or not my perspective is understandable.

Remains unclear to me:  can you define precisely what it is you think
floor()
should do?  Feel free to assume 754 arithmetic.  BTW, note that Python isn't
making up its own meaning for floor(); math.floor() inherits the function of
the same name from the platform C library, and the C std mandates its
behavior.  When explaining why it returns "large" floats unchanged, I was
explaining why the C committee chose to do that.  Indeed, I don't know of
any
language that defines floor() in any other way.

<orcnote>
OK, I think I have addressed that.  I am not sure why the C committee chose
to do what they did.  It is clear what the definition is, and it seems
carefully crafted.  I do not dispute that this is a fine approach for C
Language.  My concern is higher level than that.  It seems I have failed to
make that understood.
</orcnote>

fighting-the-universe-is-a-low-success-hobby<wink>-ly y'rs  - tim



--
http://mail.python.org/mailman/listinfo/python-list





More information about the Python-list mailing list