Browse Source

F#: BigRational.FromDecimal #716

v4
Christoph Ruegg 6 years ago
parent
commit
19d3527dae
  1. 21
      src/FSharp.Tests/BigRationalTests.fs
  2. 14
      src/FSharp/BigRational.fs
  3. 2
      src/FSharp/BigRational.fsi

21
src/FSharp.Tests/BigRationalTests.fs

@ -300,6 +300,27 @@ type public BigRationalTests() =
//let powers = [0I .. 100I]
//powers |> List.iter (fun i -> test1All "PowN(x,i)" (fun x -> BigRational.PowN(x,int i)) (fun (p,q) -> (BigInteger.Pow(p,i),BigInteger.Pow(q,i))) vector1s)
[<Test>]
member this.FromDecimal() =
let pairs =
[
1M, 1N
100000000000000M, 100000000000000N
10000000000000000000000000000M, 10000000000000000000000000000N
100000000000000.00000000000000M, 100000000000000N
1.0000000000000000000000000000M, 1N
123456789M, 123456789N
0.123456789M, 123456789N/1000000000N
0.000000000123456789M, 123456789N/1000000000000000000N
0.000000000000000000123456789M, 123456789N/1000000000000000000000000000N
4294967295M, 4294967295N
18446744073709551615M, 18446744073709551615N
Decimal.MaxValue, 79228162514264337593543950335N
Decimal.MinValue, -79228162514264337593543950335N
-7.9228162514264337593543950335M, -79228162514264337593543950335N/10000000000000000000000000000N
]
for (decimal, rational) in pairs do
Assert.AreEqual(rational, BigRational.FromDecimal(decimal))
[<TestFixture>]

14
src/FSharp/BigRational.fs

@ -276,6 +276,20 @@ type BigRational =
static member FromBigIntFraction (numerator: BigInteger, denominator: BigInteger) =
Q (BigRationalLarge.Create (numerator, denominator))
// See https://docs.microsoft.com/en-us/dotnet/api/system.decimal.getbits
static member FromDecimal(n : decimal) =
let parts = Decimal.GetBits(n)
assert(parts.Length = 4)
let toBigInt = uint32 >> bigint
let lo = (toBigInt parts.[0]) <<< 0
let mid = (toBigInt parts.[1]) <<< 32
let hi = (toBigInt parts.[2]) <<< 64
let sign = if (parts.[3] &&& 0x80000000) = 0 then 1I else -1I
let scale = (parts.[3] >>> 16) &&& 0x7F
BigRational.FromBigIntFraction(
sign * (lo + mid + hi),
BigInteger.Pow(10I, scale))
/// Get zero as a rational number
static member Zero =
BigRational.FromInt 0

2
src/FSharp/BigRational.fsi

@ -62,6 +62,8 @@ type BigRational =
static member FromIntFraction : int * int -> BigRational
static member FromBigIntFraction : BigInteger * BigInteger -> BigRational
static member FromDecimal : decimal -> BigRational
static member ToDouble: BigRational -> float
static member ToBigInt: BigRational -> BigInteger
static member ToInt32 : BigRational -> int

Loading…
Cancel
Save