Make toRational proc to loop through integers (#6633)

This commit is contained in:
konqoro
2017-10-30 23:59:03 +02:00
committed by Andreas Rumpf
parent c182d37f45
commit 6315c641be

View File

@@ -39,7 +39,7 @@ proc toRational*[T:SomeInteger](x: T): Rational[T] =
result.num = x
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
## that approximates to `x`, where the denominator is
## smaller than `n` (default is the largest possible
@@ -60,19 +60,17 @@ proc toRational*(x: float, n: int = high(int)): Rational[int] =
var
m11, m22 = 1
m12, m21 = 0
ai = x.int
ai = int(x)
x = x
while m21.float * ai.float + m22.float <= n.float:
while m21 * ai + m22 <= n:
swap m12, m11
swap m22, m21
m11 = m12 * ai + m11
m21 = m22 * ai + m21
if x == ai.float: # division by zero
break
if x > 0x7FFFFFFF.float: # representation failure
break
x = 1.0 / (x - ai.float)
ai = x.int
if x == float(ai): break # division by zero
x = 1/(x - float(ai))
if x > float(high(int32)): break # representation failure
ai = int(x)
result = m11 // m21
proc toFloat*[T](x: Rational[T]): float =
@@ -325,15 +323,14 @@ when isMainModule:
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
assert toInt(z) == 0
assert $toRational(0.98765432) == "5376864444397469455/5444075255396513284"
assert $toRational(PI) == "8566508067901016491/2726804208086097199"
assert toRational(0.1, 1000000) == 1 // 10
assert toRational(0.9, 1000000) == 9 // 10
#assert toRational(PI) == 80143857 // 25510582
assert toRational(0.98765432) == 2111111029 // 2137499919
assert toRational(PI) == 817696623 // 260280919
assert toRational(0.1) == 1 // 10
assert toRational(0.9) == 9 // 10
assert toRational(0.0) == 0 // 1
assert toRational(-0.25, 10) == 1 // -4
assert toRational(3.2, 10) == 16 // 5
assert toRational(0.33, 100) == 33 // 100
assert toRational(0.22, 50) == 11 // 50
assert toRational(-0.25) == 1 // -4
assert toRational(3.2) == 16 // 5
assert toRational(0.33) == 33 // 100
assert toRational(0.22) == 11 // 50
assert toRational(10.0) == 10 // 1