首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell:如何为(BigFloat e)定义二进制实例?

Haskell:如何为(BigFloat e)定义二进制实例?
EN

Stack Overflow用户
提问于 2022-08-21 21:17:28
回答 1查看 140关注 0票数 1

如何为Data.Number.BigFloat定义二进制实例?

我通过编写以下内容为LongDouble定义了一个实例:

代码语言:javascript
复制
instance Binary LongDouble where
    put d = put (decodeFloat d)
    get   = do
        x <- get
        y <- get
        return $! encodeFloat x y

然而,尝试以下操作不起作用:

代码语言:javascript
复制
instance Binary (BigFloat e) where
    put d = put (decodeFloat d )
    get   = do
        x <- get
        y <- get
        return $! encodeFloat x y

GHC给出了以下错误消息:

代码语言:javascript
复制
/home/usr/Documents/src/Lib.hs:27:18: error:
    • No instance for (Epsilon e) arising from a use of ‘decodeFloat’
      Possible fix:
        add (Epsilon e) to the context of the instance declaration
    • In the first argument of ‘put’, namely ‘(decodeFloat d)’
      In the expression: put (decodeFloat d)
      In an equation for ‘put’: put d = put (decodeFloat d)
   |
27 |     put d = put (decodeFloat d )
   |                  ^^^^^^^^^^^^^

/home/usr/Documents/src/Lib.hs:31:19: error:
    • No instance for (Epsilon e) arising from a use of ‘encodeFloat’
      Possible fix:
        add (Epsilon e) to the context of the instance declaration
    • In the second argument of ‘($!)’, namely ‘encodeFloat x y’
      In a stmt of a 'do' block: return $! encodeFloat x y
      In the expression:
        do x <- get
           y <- get
           return $! encodeFloat x y
   |
31 |         return $! encodeFloat x y

如果我为e提供了一个特定类型,比如Prec500,我会得到以下消息:

代码语言:javascript
复制
• Illegal instance declaration for ‘Binary (BigFloat Prec500)’
    (All instance types must be of the form (T a1 ... an)
     where a1 ... an are *distinct type variables*,
     and each type variable appears at most once in the instance head.
     Use FlexibleInstances if you want to disable this.)
• In the instance declaration for ‘Binary (BigFloat Prec500)’

并且使用FlexibleInstances编译,但没有得到正确编码的数字。

以下内容也编译但也没有正确编码:

代码语言:javascript
复制
instance Epsilon e => Binary (BigFloat e) where
    put d = put (decodeFloat d )
    get   = do
        x <- get
        y <- get
        return $! encodeFloat x y
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-21 22:13:36

这个BigFloat似乎做得不太好.问题在于:

代码语言:javascript
复制
> floatDigits (0 :: BigFloat Prec500)
-9223372036854775808

(正确答案应该是500。)我承认我不完全理解为什么会发生这种情况,但从源头上看,floatDigits的计算方法是通过获取精度的日志--但是log是发生在Doubles上的事情,Double没有足够的精度来表示1e-500。因此,计算数字计数的方法从一开始就注定要失败。

为什么我说我不完全明白?我在消息来源中看到了以下几点:

代码语言:javascript
复制
floatDigits (BF m _) =
    floor $ logBase base $ recip $ fromRational $ precision m

从我的阅读来看,fromRational应该生产0 :: Double。但如果这是真的,最终的值将是0,而不是minBound

代码语言:javascript
复制
> floor $ logBase 10 $ recip $ (0 :: Double) :: Int
0

所以也许有一些不可靠的重写正在进行或什么的。

无论如何,这种类型的适当实现应该有不同的工作方式--例如,拥有一个比Epsilon更信息丰富的类,它可以将精度报告为基数和指数。(另一种可能的想法是让floatRadix返回recip precisionfloatDigits返回1,但如果精度不是整数的倒数,这就有一些奇怪之处。)

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73438297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档