[Python-ideas] Fix some special cases in Fractions?

Nicolas Rolin nicolas.rolin at tiime.fr
Thu Aug 30 09:05:23 EDT 2018


I think you could take the implementation further and decide that any power
of Fraction(1) is Fraction(1) and any positive power of Fraction(0) is
Fraction(0).
I woudn't be shocked that Fraction(1) ** 3.7 == Fraction(1) and Fraction(0)
** 3.7 == 0.

However the implementation for Fraction(-1) seems a bit to "ad hoc", and
break some expected behavior of the powers.
For exemple in your code Fraction(-2) ** Fraction(2, 3) != Fraction(-1) **
Fraction(2, 3) * Fraction(2) ** Fraction(2, 3), whereas floats respect this.
You could change the code so that the property (a *b) ** c == a**c *b**c,
but idk how hard it is.

2018-08-30 13:31 GMT+02:00 Neil Girdhar <mistersheik at gmail.com>:

> Thanks for the feedback.
>
> On Thu, Aug 30, 2018 at 7:13 AM Paul Moore <p.f.moore at gmail.com> wrote:
>
>> (You're still not fixing your mail headers. Please do, it's hard to be
>> bothered responding if I keep having to fix your mails in order to do
>> so).
>>
>> On Thu, 30 Aug 2018 at 11:28, Neil Girdhar <mistersheik at gmail.com> wrote:
>> >
>> > But I'm only asking for fractional powers of -1, 0, and 1.  Is that
>> really a complex issue?
>>
>> Yes. (Even ignoring the oh-so-tempting complex number joke ;-)). As
>> has been seen here there's no agreement on the "right" choice of which
>> root of -1 to choose. Or possibly more accurately, no-one else is
>> agreeing with your suggestion that we choose a different option for
>> the case you're arguing over.
>>
>> And to be 100% precise, you asked for the results of three *very
>> specific* calculations to change. I guess you actually want something
>> more general - or are you really OK with (for example)
>> Fraction(-1,1)**Fraction(2,3) changing as you request, but
>> Fraction(-2,1)**Fraction(2,3) remaining as it currently is?
>
>
> Powers of other numbers have to keep the same behavior since in general
> those kinds of expressions don't create rational numbers.
>
>
>> You still
>> haven't clarified (no-one has particularly asked yet - you may
>> consider this a request to do so if you like) how you propose in
>> general that the result of
>>
>>     Fraction(-1,1) ** Fraction(a, b)
>> and/or
>>     Fraction(1,1) ** Fraction(a, b)
>> or maybe even more generally
>>     Fraction(c,d) ** Fraction(a,b)
>>
>> would change. What exactly are the special cases you want to define
>> different results for? What is the process for choosing the result?
>>
>
> Here's my proposed method:
>
> class Fraction:
>     def __pow__(a, b):
>         """a ** b
>         If b is not an integer, the result will be a float or complex
>         since roots are generally irrational. If b is an integer, the
>         result will be rational.
>         """
>         if isinstance(b, numbers.Rational):
>             if b.denominator == 1:
>                 power = b.numerator
>                 if power >= 0:
>                     return Fraction(a._numerator ** power,
>                                     a._denominator ** power,
>                                     _normalize=False)
>                 elif a._numerator >= 0:
>                     return Fraction(a._denominator ** -power,
>                                     a._numerator ** -power,
>                                     _normalize=False)
>                 else:
>                     return Fraction((-a._denominator) ** -power,
>                                     (-a._numerator) ** -power,
>                                     _normalize=False)
>             elif a == -1 and b.denominator % 2 == 1:
>                 return Fraction(-1 if b.numerator % 2 == 1 else 1)
>             elif a == 0:
>                 if b > 0:
>                     return Fraction(0)
>                 else:
>                     raise ZeroDivisionError(
>                         "0 cannot be raised to a negative power")
>             elif a == 1:
>                 return Fraction(1)
>             else:
>                 # A fractional power will generally produce an
>                 # irrational number.
>                 return float(a) ** float(b)
>         else:
>             return float(a) ** b
>
> Compare it with https://github.com/python/cpython/blob/3.7/Lib/
> fractions.py#L448
>
>
>>
>> > You are right that the fractional power of -1 and 1 has multiple
>> values, but the fractional power of zero has a unique value.
>>
>> And that part of your proposal has not generated much controversy.
>> Maybe if you proposed only that, you might get that change made? I
>> haven't considered the ramifications of that because the discussions
>> about -1 are obscuring it, but it might be relatively uncontroversial.
>>
>
> Fair enough.
>
>>
>> Paul
>>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>


-- 

--
*Nicolas Rolin* | Data Scientist
+ 33 631992617 - nicolas.rolin at tiime.fr <prenom.nom at tiime.fr>


*15 rue Auber, **75009 Paris*
*www.tiime.fr <http://www.tiime.fr>*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180830/515f6e2f/attachment.html>


More information about the Python-ideas mailing list