F#中是否存在任意精度浮点数? BigFloat之类的东西?

时间:2013-03-17 11:19:59

标签: f# floating-point

F#中是否有数据类型可以让我计算浮点到任意/大量的小数位?像浮点数相当于BigInt。

我想做点什么

 myLargeFloat = 1.0/7.0
 printfn "%12.500f" myLargeFloat // get the recurring cycle "0.142857142857142857...<500 digits long>"

我使用BigInt通过将分子乘以bigint来获得精度。

 myLargeFloat = (bigint.Pow(10I,500)/7I)

有更好的方法吗?

3 个答案:

答案 0 :(得分:3)

F#Powerpack中的BigRational定义如下:

   [<CustomEquality; CustomComparison>]
   [<StructuredFormatDisplay("{StructuredDisplayString}N")>]
   type BigRational =
       | Z of BigInteger
       | Q of BigRationalLarge

BigRationalLarge定义为:

[<CustomEquality; CustomComparison>]
type BigRationalLarge = 
    | Q of BigInteger * BigInteger

要以1000精度打印BigInt,请执行以下操作:

let factorial n = Seq.fold ( * ) 1I [1I .. n]

printf "Factorial of 1000 is %A" (factorial 1000I) 

取自here

查看BigRationalLarge类型here

有多种方法可以将其转换为其他类型进行打印:

   static member ToDouble(n:BigRational) = 
        match n with
        | Z z -> ToDoubleI z
        | Q q -> BigRationalLarge.ToDouble q

    static member ToBigInt(n:BigRational) = 
        match n with 
        | Z z -> z
        | Q q -> BigRationalLarge.integer q 

    static member ToInt32(n:BigRational) = 
        match n with 
        | Z z -> ToInt32I(z)
        | Q q -> ToInt32I(BigRationalLarge.integer q )

转换为double看起来像这样:

   static member ToDouble (Q(p,q)) = 
        ToDoubleI p / ToDoubleI q

将其打印为分子和分母组合的默认方式:

   override n.ToString() =
        let (Q(p,q)) = n 
        if q.IsOne then p.ToString() 
        else p.ToString() + "/" + q.ToString()

这些都不能帮助我们获得更高的精确度。在指定要打印的小数位数时无法打印它。

所以回答你的问题:

您可以使用BigInt的两个BigRational部分创建一个打印所需值的函数,或者您可以编写一个全新的类型来为您执行此操作,但是没有现在就是这样的。

答案 1 :(得分:2)

F# PowerPack中有一个BigRational类型。另请参阅http://tomasp.net/blog/powerpack-numeric.aspx

答案 2 :(得分:1)

如果真正需要任意精度浮点数,则必须使用@ mydogisbox的方法。如果您只需要精度高于float(即System.Double)的内容,则可以尝试使用decimal类型;它是System.Decimal的别名,它是128位二进制编码十进制(BCD)的.NET实现。它比float精确得多,但也慢得多(如10-20倍)。