So developers everywhere implement their own. Duration math depends crucially on rational arithmetic and so Víctor and I are no exception. My first implementation was in 2005, I think Víctor followed soon after, and we've shared a relatively robust implementation this year. And, just this week, we've reimplemented yet again.
Some features.
The initializer requires
numerator
but leaves denominator
optional.
>>> p = Rational(13, 8)
>>> p
13/8
>>> q = Rational(2)
>>> q
2
Unary negation, inversion and absolute value work the way you think they do.
>>> -p
-13/8
>>> ~p
8/13
>>> abs(p)
13/8
So do the inequalities.
>>> p < q, p <= q, p == q, p >= q, p > q
(True, True, False, False, False)
Integers work too.
>>> p
13/8
>>> p < 2, p <= 2, p == 2, p > 2, p >= 2
(True, True, False, False, False)
Arithmetic
__add__
, __sub__
, __mul__
, __div__
and even __truediv__
all work.
>>> p, q
(13/8, 2)
>>> p + q
29/8
>>> p - q
-3/8
>>> p * q
13/4
>>> p / q
13/16
Things that are supposed to be commutative are. Others aren't.
>>> p + q == q + p, p * q == q * p
(True, True)
>>> p - q == q - p, p / q == q / p
(False, False)
Right-operators
__radd__
, __rsub__
, __rmul__
, __rdiv__
and __rtruediv__
make integers work here too.
>>> p
13/8
>>> 2 + p
29/8
>>> 2 - p
-3/8
>>> 2 * p
13/4
>>> 2 / p
16/13
Floor division comes up every once in a while.
>>> Rational(93, 8) // 2
5
And you can compose with rational
mod
.
>>> Rational(93, 8) % 2
13/8
>>> Rational(93, 8) % Rational(2, 3)
7/24
>>> 93 % Rational(2, 3)
1/3
Coercion works for
int
and float
>>> p
13/8
>>> int(p)
1
>>> float(p)
1.625
And there're
set
and copy
methods.
>>> p.set(15, 16)
>>> p
15/16
>>> p.copy( )
15/16
>>> id(p) == id(_)
False
The code is here. If you like -- or find bugs -- let us know.
No comments:
Post a Comment