parent
39230422d0
commit
065264eae1
2 changed files with 32 additions and 30 deletions
|
|
@ -28,7 +28,7 @@ type Rational*[T] = object
|
||||||
num*, den*: T
|
num*, den*: T
|
||||||
|
|
||||||
func reduce*[T: SomeInteger](x: var Rational[T]) =
|
func reduce*[T: SomeInteger](x: var Rational[T]) =
|
||||||
## Reduce the rational number `x`, so that the numerator and denominator
|
## Reduces the rational number `x`, so that the numerator and denominator
|
||||||
## have no common divisors other than 1 (and -1).
|
## have no common divisors other than 1 (and -1).
|
||||||
## If `x` is 0, raises `DivByZeroDefect`.
|
## If `x` is 0, raises `DivByZeroDefect`.
|
||||||
##
|
##
|
||||||
|
|
@ -50,7 +50,7 @@ func reduce*[T: SomeInteger](x: var Rational[T]) =
|
||||||
raise newException(DivByZeroDefect, "division by zero")
|
raise newException(DivByZeroDefect, "division by zero")
|
||||||
|
|
||||||
func initRational*[T: SomeInteger](num, den: T): Rational[T] =
|
func initRational*[T: SomeInteger](num, den: T): Rational[T] =
|
||||||
## Create a new rational number with numerator `num` and denominator `den`.
|
## Creates a new rational number with numerator `num` and denominator `den`.
|
||||||
## `den` must not be 0.
|
## `den` must not be 0.
|
||||||
##
|
##
|
||||||
## **Note:** `den != 0` is not checked when assertions are turned off.
|
## **Note:** `den != 0` is not checked when assertions are turned off.
|
||||||
|
|
@ -68,14 +68,14 @@ func `//`*[T](num, den: T): Rational[T] =
|
||||||
initRational[T](num, den)
|
initRational[T](num, den)
|
||||||
|
|
||||||
func `$`*[T](x: Rational[T]): string =
|
func `$`*[T](x: Rational[T]): string =
|
||||||
## Turn a rational number into a string.
|
## Turns a rational number into a string.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
doAssert $(1 // 2) == "1/2"
|
doAssert $(1 // 2) == "1/2"
|
||||||
|
|
||||||
result = $x.num & "/" & $x.den
|
result = $x.num & "/" & $x.den
|
||||||
|
|
||||||
func toRational*[T: SomeInteger](x: T): Rational[T] =
|
func toRational*[T: SomeInteger](x: T): Rational[T] =
|
||||||
## Convert some integer `x` to a rational number.
|
## Converts some integer `x` to a rational number.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
doAssert toRational(42) == 42 // 1
|
doAssert toRational(42) == 42 // 1
|
||||||
|
|
||||||
|
|
@ -92,9 +92,8 @@ func toRational*(x: float,
|
||||||
# David Eppstein / UC Irvine / 8 Aug 1993
|
# David Eppstein / UC Irvine / 8 Aug 1993
|
||||||
# With corrections from Arno Formella, May 2008
|
# With corrections from Arno Formella, May 2008
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
import std/math
|
let x = 1.2
|
||||||
|
doAssert x.toRational.toFloat == x
|
||||||
doAssert almostEqual(PI.toRational.toFloat, PI)
|
|
||||||
|
|
||||||
var
|
var
|
||||||
m11, m22 = 1
|
m11, m22 = 1
|
||||||
|
|
@ -113,40 +112,40 @@ func toRational*(x: float,
|
||||||
result = m11 // m21
|
result = m11 // m21
|
||||||
|
|
||||||
func toFloat*[T](x: Rational[T]): float =
|
func toFloat*[T](x: Rational[T]): float =
|
||||||
## Convert a rational number `x` to a `float`.
|
## Converts a rational number `x` to a `float`.
|
||||||
x.num / x.den
|
x.num / x.den
|
||||||
|
|
||||||
func toInt*[T](x: Rational[T]): int =
|
func toInt*[T](x: Rational[T]): int =
|
||||||
## Convert a rational number `x` to an `int`. Conversion rounds towards 0 if
|
## Converts a rational number `x` to an `int`. Conversion rounds towards 0 if
|
||||||
## `x` does not contain an integer value.
|
## `x` does not contain an integer value.
|
||||||
x.num div x.den
|
x.num div x.den
|
||||||
|
|
||||||
func `+`*[T](x, y: Rational[T]): Rational[T] =
|
func `+`*[T](x, y: Rational[T]): Rational[T] =
|
||||||
## Add two rational numbers.
|
## Adds two rational numbers.
|
||||||
let common = lcm(x.den, y.den)
|
let common = lcm(x.den, y.den)
|
||||||
result.num = common div x.den * x.num + common div y.den * y.num
|
result.num = common div x.den * x.num + common div y.den * y.num
|
||||||
result.den = common
|
result.den = common
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `+`*[T](x: Rational[T], y: T): Rational[T] =
|
func `+`*[T](x: Rational[T], y: T): Rational[T] =
|
||||||
## Add the rational `x` to the int `y`.
|
## Adds the rational `x` to the int `y`.
|
||||||
result.num = x.num + y * x.den
|
result.num = x.num + y * x.den
|
||||||
result.den = x.den
|
result.den = x.den
|
||||||
|
|
||||||
func `+`*[T](x: T, y: Rational[T]): Rational[T] =
|
func `+`*[T](x: T, y: Rational[T]): Rational[T] =
|
||||||
## Add the int `x` to the rational `y`.
|
## Adds the int `x` to the rational `y`.
|
||||||
result.num = x * y.den + y.num
|
result.num = x * y.den + y.num
|
||||||
result.den = y.den
|
result.den = y.den
|
||||||
|
|
||||||
func `+=`*[T](x: var Rational[T], y: Rational[T]) =
|
func `+=`*[T](x: var Rational[T], y: Rational[T]) =
|
||||||
## Add the rational `y` to the rational `x` in-place.
|
## Adds the rational `y` to the rational `x` in-place.
|
||||||
let common = lcm(x.den, y.den)
|
let common = lcm(x.den, y.den)
|
||||||
x.num = common div x.den * x.num + common div y.den * y.num
|
x.num = common div x.den * x.num + common div y.den * y.num
|
||||||
x.den = common
|
x.den = common
|
||||||
reduce(x)
|
reduce(x)
|
||||||
|
|
||||||
func `+=`*[T](x: var Rational[T], y: T) =
|
func `+=`*[T](x: var Rational[T], y: T) =
|
||||||
## Add the int `y` to the rational `x` in-place.
|
## Adds the int `y` to the rational `x` in-place.
|
||||||
x.num += y * x.den
|
x.num += y * x.den
|
||||||
|
|
||||||
func `-`*[T](x: Rational[T]): Rational[T] =
|
func `-`*[T](x: Rational[T]): Rational[T] =
|
||||||
|
|
@ -155,64 +154,64 @@ func `-`*[T](x: Rational[T]): Rational[T] =
|
||||||
result.den = x.den
|
result.den = x.den
|
||||||
|
|
||||||
func `-`*[T](x, y: Rational[T]): Rational[T] =
|
func `-`*[T](x, y: Rational[T]): Rational[T] =
|
||||||
## Subtract two rational numbers.
|
## Subtracts two rational numbers.
|
||||||
let common = lcm(x.den, y.den)
|
let common = lcm(x.den, y.den)
|
||||||
result.num = common div x.den * x.num - common div y.den * y.num
|
result.num = common div x.den * x.num - common div y.den * y.num
|
||||||
result.den = common
|
result.den = common
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `-`*[T](x: Rational[T], y: T): Rational[T] =
|
func `-`*[T](x: Rational[T], y: T): Rational[T] =
|
||||||
## Subtract the int `y` from the rational `x`.
|
## Subtracts the int `y` from the rational `x`.
|
||||||
result.num = x.num - y * x.den
|
result.num = x.num - y * x.den
|
||||||
result.den = x.den
|
result.den = x.den
|
||||||
|
|
||||||
func `-`*[T](x: T, y: Rational[T]): Rational[T] =
|
func `-`*[T](x: T, y: Rational[T]): Rational[T] =
|
||||||
## Subtract the rational `y` from the int `x`.
|
## Subtracts the rational `y` from the int `x`.
|
||||||
result.num = x * y.den - y.num
|
result.num = x * y.den - y.num
|
||||||
result.den = y.den
|
result.den = y.den
|
||||||
|
|
||||||
func `-=`*[T](x: var Rational[T], y: Rational[T]) =
|
func `-=`*[T](x: var Rational[T], y: Rational[T]) =
|
||||||
## Subtract the rational `y` from the rational `x` in-place.
|
## Subtracts the rational `y` from the rational `x` in-place.
|
||||||
let common = lcm(x.den, y.den)
|
let common = lcm(x.den, y.den)
|
||||||
x.num = common div x.den * x.num - common div y.den * y.num
|
x.num = common div x.den * x.num - common div y.den * y.num
|
||||||
x.den = common
|
x.den = common
|
||||||
reduce(x)
|
reduce(x)
|
||||||
|
|
||||||
func `-=`*[T](x: var Rational[T], y: T) =
|
func `-=`*[T](x: var Rational[T], y: T) =
|
||||||
## Subtract the int `y` from the rational `x` in-place.
|
## Subtracts the int `y` from the rational `x` in-place.
|
||||||
x.num -= y * x.den
|
x.num -= y * x.den
|
||||||
|
|
||||||
func `*`*[T](x, y: Rational[T]): Rational[T] =
|
func `*`*[T](x, y: Rational[T]): Rational[T] =
|
||||||
## Multiply two rational numbers.
|
## Multiplies two rational numbers.
|
||||||
result.num = x.num * y.num
|
result.num = x.num * y.num
|
||||||
result.den = x.den * y.den
|
result.den = x.den * y.den
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `*`*[T](x: Rational[T], y: T): Rational[T] =
|
func `*`*[T](x: Rational[T], y: T): Rational[T] =
|
||||||
## Multiply the rational `x` with the int `y`.
|
## Multiplies the rational `x` with the int `y`.
|
||||||
result.num = x.num * y
|
result.num = x.num * y
|
||||||
result.den = x.den
|
result.den = x.den
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `*`*[T](x: T, y: Rational[T]): Rational[T] =
|
func `*`*[T](x: T, y: Rational[T]): Rational[T] =
|
||||||
## Multiply the int `x` with the rational `y`.
|
## Multiplies the int `x` with the rational `y`.
|
||||||
result.num = x * y.num
|
result.num = x * y.num
|
||||||
result.den = y.den
|
result.den = y.den
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `*=`*[T](x: var Rational[T], y: Rational[T]) =
|
func `*=`*[T](x: var Rational[T], y: Rational[T]) =
|
||||||
## Multiply the rational `x` by `y` in-place.
|
## Multiplies the rational `x` by `y` in-place.
|
||||||
x.num *= y.num
|
x.num *= y.num
|
||||||
x.den *= y.den
|
x.den *= y.den
|
||||||
reduce(x)
|
reduce(x)
|
||||||
|
|
||||||
func `*=`*[T](x: var Rational[T], y: T) =
|
func `*=`*[T](x: var Rational[T], y: T) =
|
||||||
## Multiply the rational `x` by the int `y` in-place.
|
## Multiplies the rational `x` by the int `y` in-place.
|
||||||
x.num *= y
|
x.num *= y
|
||||||
reduce(x)
|
reduce(x)
|
||||||
|
|
||||||
func reciprocal*[T](x: Rational[T]): Rational[T] =
|
func reciprocal*[T](x: Rational[T]): Rational[T] =
|
||||||
## Calculate the reciprocal of `x` (`1/x`).
|
## Calculates the reciprocal of `x` (`1/x`).
|
||||||
## If `x` is 0, raises `DivByZeroDefect`.
|
## If `x` is 0, raises `DivByZeroDefect`.
|
||||||
if x.num > 0:
|
if x.num > 0:
|
||||||
result.num = x.den
|
result.num = x.den
|
||||||
|
|
@ -224,31 +223,31 @@ func reciprocal*[T](x: Rational[T]): Rational[T] =
|
||||||
raise newException(DivByZeroDefect, "division by zero")
|
raise newException(DivByZeroDefect, "division by zero")
|
||||||
|
|
||||||
func `/`*[T](x, y: Rational[T]): Rational[T] =
|
func `/`*[T](x, y: Rational[T]): Rational[T] =
|
||||||
## Divide the rational `x` by the rational `y`.
|
## Divides the rational `x` by the rational `y`.
|
||||||
result.num = x.num * y.den
|
result.num = x.num * y.den
|
||||||
result.den = x.den * y.num
|
result.den = x.den * y.num
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `/`*[T](x: Rational[T], y: T): Rational[T] =
|
func `/`*[T](x: Rational[T], y: T): Rational[T] =
|
||||||
## Divide the rational `x` by the int `y`.
|
## Divides the rational `x` by the int `y`.
|
||||||
result.num = x.num
|
result.num = x.num
|
||||||
result.den = x.den * y
|
result.den = x.den * y
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `/`*[T](x: T, y: Rational[T]): Rational[T] =
|
func `/`*[T](x: T, y: Rational[T]): Rational[T] =
|
||||||
## Divide the int `x` by the rational `y`.
|
## Divides the int `x` by the rational `y`.
|
||||||
result.num = x * y.den
|
result.num = x * y.den
|
||||||
result.den = y.num
|
result.den = y.num
|
||||||
reduce(result)
|
reduce(result)
|
||||||
|
|
||||||
func `/=`*[T](x: var Rational[T], y: Rational[T]) =
|
func `/=`*[T](x: var Rational[T], y: Rational[T]) =
|
||||||
## Divide the rational `x` by the rational `y` in-place.
|
## Divides the rational `x` by the rational `y` in-place.
|
||||||
x.num *= y.den
|
x.num *= y.den
|
||||||
x.den *= y.num
|
x.den *= y.num
|
||||||
reduce(x)
|
reduce(x)
|
||||||
|
|
||||||
func `/=`*[T](x: var Rational[T], y: T) =
|
func `/=`*[T](x: var Rational[T], y: T) =
|
||||||
## Divide the rational `x` by the int `y` in-place.
|
## Divides the rational `x` by the int `y` in-place.
|
||||||
x.den *= y
|
x.den *= y
|
||||||
reduce(x)
|
reduce(x)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,5 +96,8 @@ template main() =
|
||||||
doAssert floorMod(3 // 10, 1 // 1) == 3 // 10
|
doAssert floorMod(3 // 10, 1 // 1) == 3 // 10
|
||||||
doAssert floorMod(-3 // 10, 1 // 1) == 7 // 10
|
doAssert floorMod(-3 // 10, 1 // 1) == 7 // 10
|
||||||
|
|
||||||
|
when sizeof(int) == 8:
|
||||||
|
doAssert almostEqual(PI.toRational.toFloat, PI)
|
||||||
|
|
||||||
static: main()
|
static: main()
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue