mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-01 03:24:41 +00:00
Support div, mod, floorDiv and floorMod for Rationals (#7918)
* Support `div`, `mod`, floorDiv and floorMod for Ratinoals. * Bug fix and add tests. * Update changelog
This commit is contained in:
@@ -241,6 +241,33 @@ proc abs*[T](x: Rational[T]): Rational[T] =
|
||||
result.num = abs x.num
|
||||
result.den = abs x.den
|
||||
|
||||
proc `div`*[T: SomeInteger](x, y: Rational[T]): T =
|
||||
## Computes the rational truncated division.
|
||||
(x.num * y.den) div (y.num * x.den)
|
||||
|
||||
proc `mod`*[T: SomeInteger](x, y: Rational[T]): Rational[T] =
|
||||
## Computes the rational modulo by truncated division (remainder).
|
||||
## This is same as ``x - (x div y) * y``.
|
||||
result = ((x.num * y.den) mod (y.num * x.den)) // (x.den * y.den)
|
||||
reduce(result)
|
||||
|
||||
proc floorDiv*[T: SomeInteger](x, y: Rational[T]): T =
|
||||
## Computes the rational floor division.
|
||||
##
|
||||
## Floor division is conceptually defined as ``floor(x / y)``.
|
||||
## This is different from the ``div`` operator, which is defined
|
||||
## as ``trunc(x / y)``. That is, ``div`` rounds towards ``0`` and ``floorDiv``
|
||||
## rounds down.
|
||||
floorDiv(x.num * y.den, y.num * x.den)
|
||||
|
||||
proc floorMod*[T: SomeInteger](x, y: Rational[T]): Rational[T] =
|
||||
## Computes the rational modulo by floor division (modulo).
|
||||
##
|
||||
## This is same as ``x - floorDiv(x, y) * y``.
|
||||
## This proc behaves the same as the ``%`` operator in python.
|
||||
result = floorMod(x.num * y.den, y.num * x.den) // (x.den * y.den)
|
||||
reduce(result)
|
||||
|
||||
proc hash*[T](x: Rational[T]): Hash =
|
||||
## Computes hash for rational `x`
|
||||
# reduce first so that hash(x) == hash(y) for x == y
|
||||
@@ -339,3 +366,12 @@ when isMainModule:
|
||||
assert toRational(0.33) == 33 // 100
|
||||
assert toRational(0.22) == 11 // 50
|
||||
assert toRational(10.0) == 10 // 1
|
||||
|
||||
assert (1//1) div (3//10) == 3
|
||||
assert (-1//1) div (3//10) == -3
|
||||
assert (3//10) mod (1//1) == 3//10
|
||||
assert (-3//10) mod (1//1) == -3//10
|
||||
assert floorDiv(1//1, 3//10) == 3
|
||||
assert floorDiv(-1//1, 3//10) == -4
|
||||
assert floorMod(3//10, 1//1) == 3//10
|
||||
assert floorMod(-3//10, 1//1) == 7//10
|
||||
|
||||
Reference in New Issue
Block a user