[Python-ideas] Fwd: Trigonometry in degrees

Tim Peters tim.peters at gmail.com
Tue Jun 12 11:51:37 EDT 2018


>
>
> [Tim]

>> 1. Python's float "%" is unsuitable for argument reduction; e.g.,
> >>
> >>  >>> -1e-14 % 360.0
> >> 360.0
> >>
> >> `math.fmod` is suitable, because it's exact:
> >>
> >>  >>> math.fmod(-1e-14, 360.0)
> >> -1e-14
>


> [Greg Ewing]

> So why doesn't float % use math.fmod?
>

[Chris Angelico]

>
> https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations
> https://docs.python.org/3/reference/expressions.html#id17
> https://docs.python.org/3/reference/expressions.html#id18
>
> (the latter two being footnotes from the section in the first link)
>
> With real numbers, divmod (and thus the // and % operators) would
> always return values such that:
>
> div, mod = divmod(x, y):
> 1) div*y + mod == x
> 2) sign(mod) == sign(y)
> 3) 0 <= abs(mod) < abs(y)
>
> But with floats, you can't guarantee all three of these. The divmod
> function focuses on the first, guaranteeing the fundamental arithmetic
> equality, but to do so, it sometimes has to bend the third one and
> return mod==y.
>
> It's more that #2 is viewed as fundamental (because that's most useful for
positive integer y), and _given that_ sometimes results are fiddled to keep
#1 approximately true, and strict inequality in #3 may be sacrificed.  For
`fmod`, sign(mod) == sign(x) instead.

>>> -2 % 3
1
 >>> -2.0 % 3.0
1.0
>>> math.fmod(-2.0, 3.0)
-2.0

All mod functions, m(x, y), strive to return a result that's mathematically
exactly equal to x-n*y (for some mathematical integer `n` that may not even
be representable in the programming language).  `fmod()` is exact in that
sense, but Python's floating "%" may not be. and no float scheme such that
sign(m(x, y)) = sign(y) can be (see the original example at the top:  the
only mathematical integer `n` such that the mathematical   -1e-14 - n*360.0 is
exactly representable as a double is n==0).

The most useful mod function for floats _as floats_ would actually satisfy

    abs(m(x, y)) <= abs(y) / 2

That can be done exactly too - but then the sign of the result has
approximately nothing to do with the signs of the arguments.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180612/3d6af409/attachment-0001.html>


More information about the Python-ideas mailing list