gpt4 book ai didi

debugging - 查找 "Ratio has zero denominator"异常的根源

转载 作者:行者123 更新时间:2023-12-04 18:37:16 26 4
gpt4 key购买 nike

作为学习过程中的个人练习 haskell ,我正在尝试移植此 F# Random Art 的片段.

我没有嵌入完整的源代码以防止问题膨胀,但可用作 gist .

该程序的一个重要部分是 Expr类型:


data Expr =
VariableX
| VariableY
| Constant
| Sum Expr Expr
| Product Expr Expr
| Mod Expr Expr
| Well Expr
| Tent Expr
| Sin Expr
| Level Expr Expr Expr
| Mix Expr Expr Expr
deriving Show

和两个功能:
  • gen :: Int -> IO Expr random 在给定多次迭代的情况下生成树状结构
  • eval :: Expr -> IO (Point -> Rgb Double)遍历树并终止生成绘图函数。

  • 传递给 gen 的数字更高。产生以下异常的概率高于: Ratio has zero denominator .

    我是 Haskell 的新手,所以为了解决我尝试按上述方式编译它的问题:

    ghc RandomArt.hs -prof -auto-all -caf-all

    仅获得更多(对我来说毫无用处)信息:

    $ ./RandomArt +RTS -xc

    *** Exception (reporting due to +RTS -xc): (THUNK_STATIC), stack trace:
    GHC.Real.CAF
    --> evaluated by: Main.eval.\,
    called from Main.eval,
    called from Main.tga.pxs',
    called from Main.tga,
    called from Main.save,
    called from Main.main,
    called from :Main.CAF:main
    --> evaluated by: Main.eval.\.r,
    called from Main.eval.\,
    called from Main.eval,
    called from Main.tga.pxs',
    called from Main.tga,
    called from Main.save,
    called from Main.main,
    called from :Main.CAF:main
    *** Exception (reporting due to +RTS -xc): (THUNK_STATIC), stack trace:
    Main.tga,
    called from Main.save,
    called from Main.main,
    called from GHC.Real.CAF
    RandomArt: Ratio has zero denominator

    将生成的函数保存到 的代码TGA 文件有效,因为它是我的 previous excercize (来自 OCaml 的端口)。

    我试过执行各种 Expr来自 的树GHCi ,手动组装数据或应用程序中的功能,但我无法识别错误。

    Haskell 文档讨论了一个名为 loch 的包那应该能够编译保留的源代码行号,但我无法安装它(虽然我通常安装 cabal install 我需要的每个包)。

    老实说,这个问题有两个:
  • 错误在哪里(在这种特定情况下)?
  • 我需要掌握哪种工具才能找到这样的错误(或一般错误)?

  • 提前致谢。

    最佳答案

    异常(exception)

    让我们首先关注异常。

    寻找错误

    where's is the bug (in this specific case)?



    mod' .如果我们提供替代版本而不是 Data.Fixed 提供的版本,我们可以轻松检查这一点:
    mod' :: RealFrac a => a -> a -> a
    mod' _ 0 = error "Used mod' on 0"
    mod' a b =
    let k = floor $ a / b
    in a - (fromInteger k) * b

    我们现在得到 Used mod' on 0 .

    基本原理

    which tool do I need to master to find bugs like this (or bugs in general)?



    在这种情况下,必要的提示已经在异常的消息中:

    Ratio has zero denominator


    这意味着在 Ratio 的上下文中存在一个除以零的位置。 .所以你需要照顾你划分东西的所有地方。由于您只使用 (/)mod' ,归结为其中一个是否真的可以抛出这个异常:
  • (/)通常返回 ±Infinity如果在 Double 上使用,则除以零,
  • mod'使用 toRational在内部,它是 Ratio Integer .

  • 所以只剩下一个罪魁祸首了。请注意,如果 b,其他实现会产生相同的结果。不是零。

    实际问题

    使用 modmod'b == 0没有很好的定义。毕竟,一个 modulo operation应持有以下属性(property):
    prop_mod :: Integral n => n -> n -> Bool
    prop_mod a b =
    let m = a `mod` b
    d = a `div` b

    in a == b * d + m -- (1)
    && abs m < abs b -- (2)

    如果 b == 0 , 不存在任何对 (d, m)这样 (1) (2) 持有。如果我们放宽这个定律并把 (2) 扔掉, mod 的结果不一定是唯一的了。这导致以下定义:
    mod' :: RealFrac a => a -> a -> a
    mod' a 0 = a -- this is arbitrary
    mod' a b =
    let k = floor $ a / b
    in a - (fromInteger k) * b

    然而,这是一个任意的定义。你必须问自己,“如果我不能以理智的方式使用 mod,我真正想做什么”。因为 F# 显然没有提示 a % 0 ,看看他们的文档。

    无论哪种方式,您都不能使用库 mod函数,因为它们不是为零分母定义的。

    关于debugging - 查找 "Ratio has zero denominator"异常的根源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32724534/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com