Message 59650 - Python tracker (original) (raw)

Decimal.from_rational(Rat(1, 3)) wouldn't be lossless

It should be implemented as Decimal(1)/Decimal(3) and then let the context handle any inexactness.

Rational.from_decimal is easier than from_float.

Yes. Just use Decimal.as_tuple() to get the integer components.

Then Decimal.from_rational() could rely on just numbers. Rational, so it would be independent of this module. Is that a method you'd want on Decimal anyway?

Instead, just expand the decimal constructor to accept a rational input.

Regarding float->rational, I propose to refuse Rational(1.1) for the same reasons as Decimal(1.1) is refused,

+1

but to add a separate constructor (a class method?) that converts a float to a rational exactly (as long as it isn't nan or inf), large denominators be damned. This can help people who are interested in taking floating point numbers apart.

Here's how to pick the integer components out of a float:

mant, exp = math.frexp(x) mant, exp = int(mant * 2.0 ** 53), exp-53

  • Likewise, follow decimal's lead in avoiding all automatic coercions from floats:
    Rational(3,10) + 0.3 for example. The two don't mix.

I'm reluctant to remove the fallback to float,

You will need some plan to scale-down long integers than exceed the range of floats (right shifting the numerator and denominator until they fit).