[Python-ideas] Fwd: Trigonometry in degrees

Tim Peters tim.peters at gmail.com
Sun Jun 17 01:57:24 EDT 2018

[Steven D'Aprano <steve at pearwood.info>]

> Thanks Tim!

You're welcome ;-)

> Reading your digressions on the minutia of floating point maths is
> certainly an education. It makes algebra and real-valued mathematics
> seem easy in comparison.

Hard to say, really.  The problem with floating point is that it's so
God-awful lumpy - special cases all over the place.  Signaling and quiet
NaNs; signed infinities; signed zeroes; normal finites all with the same
number of bits, but where the gap between numbers changes abruptly at
power-of-2 boundaries; subnormals where the gap remains the same across
power-of-2 boundaries, but the number of _bits_ changes abruptly; all "the
rules" break down when you get too close to overflow or underflow; four
rounding modes to worry about; and a whole pile of technically defined
exceptional conditions and related traps & flags.

Ignoring all that, though, it's pretty easy ;-)  754 was dead serious about
requiring results act is if a single rounding is done to the infinitely
precise result, and that actually allows great simplification in reasoning.

The trend these days appears to be using automated theorem-proving systems
to keep track of the mountain of interacting special cases.  Those have
advanced enough that we may even be on the edge of getting
provably-correctly-rounded transcendental functions with reasonable speed.
Although it's not clear people will be able to understand the proofs ;-)

I still haven't got over Mark Dickinson's demonstration a few years
> back that under Decimal floating point, but not binary, it is possible
> for the ordinary arithmetic average (x+y)/2 to be outside of the
> range [x, y]:
> py> from decimal import getcontext, Decimal
> py> getcontext().prec = 3
> py> x = Decimal('0.516')
> py> y = Decimal('0.518')
> py> (x + y) / 2
> Decimal('0.515')

Ya, decimal fp doesn't really solve anything except the shallow surprise
that decimal fractions generally aren't exactly representable as binary
fractions.  Which is worth a whole lot for casual users, but doesn't
address any of the deep problems (to the contrary, it makes those a bit

I like to illustrate the above with 1-digit decimal fp, because it makes it
more apparent at once that - unlike as in binary fp - multiplication and
division by 2 may _not_ be exact in decimal fp.  We can't even average a
number "with itself" reliably:

>>> import decimal
>>> decimal.getcontext().prec = 1
>>> x = y = decimal.Decimal(8); (x+y)/2 # 10 is much bigger than 8
>>> x = y = decimal.Decimal(7); (x+y)/2 # 5 is much smaller than 7

But related things _can_ happen in binary fp too!  You have to be near the
edge of representable non-zero finites though:

>>> x = y = 1e308
>>> x
>>> (x+y)/2

Oops.  So rewrite it:

>>> x/2 + y/2

Better!  But then:

>>> x = y = float.fromhex("3p-1074")
>>> x
>>> x/2 + y/2

Oops.  A math library has to deal with everything "correctly".  Believe it
or not, this paper

    "How do you compute the midpoint of an interval?"

is solely concerned with computing the average of two IEEE doubles, yet
runs to 29(!) pages.  Almost everything you try fails for _some_ goofy

I personally write it as (x+y)/2 anyway ;-)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180617/0e572913/attachment-0001.html>

More information about the Python-ideas mailing list