1 people like it.

Rational type for units of measure

A more idiomatic definition of a Rational type with custom operators.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
// This is an alternative version of the type defined in the F# PR:
// https://visualfsharp.codeplex.com/SourceControl/network/forks/andrewjkennedy/fsharpcontrib/contribution/7632

let rec gcd a (b: int) =
  if b = 0 then a else
    gcd b (a % b)

let lcm a b = 
  (a * b) / gcd a b

type Rational = 
  { numerator: int
    denominator: int }
  static member Create(p, q) = 
    let p, q =
      if q = 0 then raise(System.DivideByZeroException())
      let g = gcd q p in
      p/g, q/g
 
    let p, q =
      if q > 0 then p, q else -p, -q
    
    { numerator = p
      denominator = q }

  static member (+) (m, n) =
    Rational.Create(m.numerator*n.denominator + n.numerator*m.denominator, m.denominator*n.denominator)

  static member (~-) m = 
    Rational.Create(-m.numerator, m.denominator)
 
  static member (*) (m, n) =
    Rational.Create(m.numerator*n.numerator, m.denominator*n.denominator)
 
  static member (/) (m, n) =
    Rational.Create(m.numerator*n.denominator, m.denominator*n.numerator)
 
  static member Abs(m) = 
    Rational.Create(abs m.numerator, m.denominator)
 
  override this.ToString() =
    if this.denominator = 1 then this.numerator.ToString() 
    else sprintf "(%A/%A)" this.numerator this.denominator
val gcd : a:int -> b:int -> int

Full name: Script.gcd
val a : int
val b : int
Multiple items
val int : value:'T -> int (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.int

--------------------
type int = int32

Full name: Microsoft.FSharp.Core.int

--------------------
type int<'Measure> = int

Full name: Microsoft.FSharp.Core.int<_>
val lcm : a:int -> b:int -> int

Full name: Script.lcm
type Rational =
  {numerator: int;
   denominator: int;}
  override ToString : unit -> string
  static member Abs : m:Rational -> Rational
  static member Create : p:int * q:int -> Rational
  static member ( + ) : m:Rational * n:Rational -> Rational
  static member ( / ) : m:Rational * n:Rational -> Rational
  static member ( * ) : m:Rational * n:Rational -> Rational
  static member ( ~- ) : m:Rational -> Rational

Full name: Script.Rational
Rational.numerator: int
Rational.denominator: int
static member Rational.Create : p:int * q:int -> Rational

Full name: Script.Rational.Create
val p : int
val q : int
val raise : exn:System.Exception -> 'T

Full name: Microsoft.FSharp.Core.Operators.raise
namespace System
Multiple items
type DivideByZeroException =
  inherit ArithmeticException
  new : unit -> DivideByZeroException + 2 overloads

Full name: System.DivideByZeroException

--------------------
System.DivideByZeroException() : unit
System.DivideByZeroException(message: string) : unit
System.DivideByZeroException(message: string, innerException: exn) : unit
val g : int
val m : Rational
val n : Rational
static member Rational.Create : p:int * q:int -> Rational
static member Rational.Abs : m:Rational -> Rational

Full name: Script.Rational.Abs
val abs : value:'T -> 'T (requires member Abs)

Full name: Microsoft.FSharp.Core.Operators.abs
val this : Rational
override Rational.ToString : unit -> string

Full name: Script.Rational.ToString
System.Int32.ToString() : string
System.Int32.ToString(provider: System.IFormatProvider) : string
System.Int32.ToString(format: string) : string
System.Int32.ToString(format: string, provider: System.IFormatProvider) : string
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
Raw view Test code New version

More information

Link:http://fssnip.net/oC
Posted:9 years ago
Author:Tomas Petricek
Tags: rational , math