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

Neil Girdhar mistersheik at gmail.com
Thu Aug 30 07:31:10 EDT 2018


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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20180830/95a70777/attachment-0001.html>


More information about the Python-ideas mailing list