Make toRational proc to loop through integers (#6633)
This commit is contained in:
parent
c182d37f45
commit
6315c641be
1 changed files with 15 additions and 18 deletions
|
|
@ -39,7 +39,7 @@ proc toRational*[T:SomeInteger](x: T): Rational[T] =
|
||||||
result.num = x
|
result.num = x
|
||||||
result.den = 1
|
result.den = 1
|
||||||
|
|
||||||
proc toRational*(x: float, n: int = high(int)): Rational[int] =
|
proc toRational*(x: float, n: int = high(int32)): Rational[int] =
|
||||||
## Calculates the best rational numerator and denominator
|
## Calculates the best rational numerator and denominator
|
||||||
## that approximates to `x`, where the denominator is
|
## that approximates to `x`, where the denominator is
|
||||||
## smaller than `n` (default is the largest possible
|
## smaller than `n` (default is the largest possible
|
||||||
|
|
@ -60,19 +60,17 @@ proc toRational*(x: float, n: int = high(int)): Rational[int] =
|
||||||
var
|
var
|
||||||
m11, m22 = 1
|
m11, m22 = 1
|
||||||
m12, m21 = 0
|
m12, m21 = 0
|
||||||
ai = x.int
|
ai = int(x)
|
||||||
x = x
|
x = x
|
||||||
while m21.float * ai.float + m22.float <= n.float:
|
while m21 * ai + m22 <= n:
|
||||||
swap m12, m11
|
swap m12, m11
|
||||||
swap m22, m21
|
swap m22, m21
|
||||||
m11 = m12 * ai + m11
|
m11 = m12 * ai + m11
|
||||||
m21 = m22 * ai + m21
|
m21 = m22 * ai + m21
|
||||||
if x == ai.float: # division by zero
|
if x == float(ai): break # division by zero
|
||||||
break
|
x = 1/(x - float(ai))
|
||||||
if x > 0x7FFFFFFF.float: # representation failure
|
if x > float(high(int32)): break # representation failure
|
||||||
break
|
ai = int(x)
|
||||||
x = 1.0 / (x - ai.float)
|
|
||||||
ai = x.int
|
|
||||||
result = m11 // m21
|
result = m11 // m21
|
||||||
|
|
||||||
proc toFloat*[T](x: Rational[T]): float =
|
proc toFloat*[T](x: Rational[T]): float =
|
||||||
|
|
@ -325,15 +323,14 @@ when isMainModule:
|
||||||
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
|
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
|
||||||
assert toInt(z) == 0
|
assert toInt(z) == 0
|
||||||
|
|
||||||
assert $toRational(0.98765432) == "5376864444397469455/5444075255396513284"
|
assert toRational(0.98765432) == 2111111029 // 2137499919
|
||||||
assert $toRational(PI) == "8566508067901016491/2726804208086097199"
|
assert toRational(PI) == 817696623 // 260280919
|
||||||
assert toRational(0.1, 1000000) == 1 // 10
|
assert toRational(0.1) == 1 // 10
|
||||||
assert toRational(0.9, 1000000) == 9 // 10
|
assert toRational(0.9) == 9 // 10
|
||||||
#assert toRational(PI) == 80143857 // 25510582
|
|
||||||
|
|
||||||
assert toRational(0.0) == 0 // 1
|
assert toRational(0.0) == 0 // 1
|
||||||
assert toRational(-0.25, 10) == 1 // -4
|
assert toRational(-0.25) == 1 // -4
|
||||||
assert toRational(3.2, 10) == 16 // 5
|
assert toRational(3.2) == 16 // 5
|
||||||
assert toRational(0.33, 100) == 33 // 100
|
assert toRational(0.33) == 33 // 100
|
||||||
assert toRational(0.22, 50) == 11 // 50
|
assert toRational(0.22) == 11 // 50
|
||||||
assert toRational(10.0) == 10 // 1
|
assert toRational(10.0) == 10 // 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue