open System.Numerics
// http://fsharpnews.blogspot.com/2013/08/implementing-rationals-in-f.html
type Rational(p: BigInteger, q: BigInteger) =
let rec gcd a (b: BigInteger) =
if b.IsZero then a else
gcd b (a % b)
let fixSign(p: BigInteger, q: BigInteger) =
if q.Sign > 0 then p, q else -p, -q
let p, q =
if q.IsZero then raise(System.DivideByZeroException())
let g = gcd q p
fixSign(p/g, q/g)
member __.Numerator = p
member __.Denominator = q
override __.ToString() =
if q.IsOne then p.ToString() else sprintf "%A/%A" p q
static member (+) (m: Rational, n: Rational) =
Rational(m.Numerator*n.Denominator + n.Numerator*m.Denominator,
m.Denominator*n.Denominator)
static member (-) (m: Rational, n: Rational) =
Rational(m.Numerator*n.Denominator - n.Numerator*m.Denominator,
m.Denominator*n.Denominator)
static member (*) (m: Rational, n: Rational) =
Rational(m.Numerator*n.Numerator, m.Denominator*n.Denominator)
static member (/) (m: Rational, n: Rational) =
Rational(m.Numerator*n.Denominator, m.Denominator*n.Numerator)
let recip (r : Rational) =
Rational(r.Denominator, r.Numerator)
let fromInteger n =
Rational(n, 1I)
let properFraction (r : Rational) =
let whole = r.Numerator / r.Denominator
let part = Rational(r.Numerator % r.Denominator, r.Denominator)
whole, part
let one = fromInteger 1I
let iterate f x =
let rec loop x =
seq {
yield x
yield! loop (f x)
}
loop x
/// https://www.cs.ox.ac.uk/jeremy.gibbons/publications/rationals.pdf
let next x =
let n, y = properFraction x
recip (fromInteger n + one - y)
let rationals =
iterate next one
[]
let main argv =
for r in rationals do
printfn "%A" r
0