You may not have expected these results but as someone who regularly
uses the fractions module I do expect them.
Why would you do the above? You're deliberately trying to create a
float with a value that you know is not representable by the float
type. The purpose of Fractions is precisely that they can represent
all rational values, hence avoiding these problems.
When I use Fractions my intention is to perform exact computation. I
am very careful to avoid allowing floating point imprecision to sneak
into my calculations. Mixing floats and fractions in computation is
not IMO a good use of duck-typing.
I would say that if type A is a strict superset of type B then the
coercion should be to type A. This is the case for float and Fraction
since any float can be represented exactly as a Fraction but the
converse is not true.
I'm surprised that Fraction(1/3) != Fraction(1, 3); after all, floats
are approximate anyway, and the float value 1/3 is more likely to be
Fraction(1, 3) than Fraction(6004799503160661, 18014398509481984).
Refuse the temptation to guess: Fraction(float) should give the exact
value of the float. It should not give one of the countably infinite
number of other possible rational numbers that would (under a
particular rounding scheme and the floating point format in question)
round to the same float. If that is the kind of equality you would
like to test for in some particular situation then you can do so by
coercing to float explicitly.
Calling Fraction(1/3) is a misunderstanding of what the fractions
module is for and how to use it. The point is to guarantee avoiding
floating point errors; this is impossible if you use floating point
computations to initialise Fractions.
Writing Fraction(1, 3) does look a bit ugly so my preferred way to
reduce the boiler-plate in a script that uses lots of Fraction
"literals" is to do:
from fractions import Fraction as F
# 1/3 + 1/9 + 1/27 + ...
limit = F('1/3') / (1 - F('1/3'))
That's not as good as dedicated syntax but with code highlighting it's
still quite readable.
Oscar