【问题标题】:f# whole number float modulus 1.0 = 1.0?f# 整数浮点模数 1.0 = 1.0?
【发布时间】:2009-08-11 13:49:49
【问题描述】:

好的,我有两个函数,第一个看起来像这样:

let dlth x = float (x.ToString().Length)

它采用浮点数并返回位数,该部分工作正常。第二个函数如下所示:

let droot x = ((x ** (1./(dlth x))) % 1.)

它采用浮点数并将其提高到等于 1.0/(位数)的幂,然后取结果并进行模数 1.0。整数应该为零。

所以对于 droot 36。它需要 (36.0 ** (1.0/2.0)) 这是 6.0 然后 6.0 mod 1.0 等于 0.0;

现在,在我尝试数字 81.0 之前,它都可以正常工作。 (以及所有高于 81 的数字都应该起作用)由于某种原因返回 1.0,从而放弃了我的模式匹配。谁能告诉我为什么会这样?

PostScript:这是 Project Euler 解决方案的一部分。如果您知道哪个问题,请不要发布 Project Euler 解决方案。我只需要帮助弄清楚为什么模数会返回有趣的结果

【问题讨论】:

    标签: .net math f# modulo


    【解决方案1】:

    浮点运算在任何语言中都充满危险。在我的盒子上

    printfn "%f" (0.9999999999999 % 1.0)        
    

    打印

    1.000000
    

    希望这将有助于引导您朝着正确的方向前进。如果你真的想知道一个浮点数是否“是一个整数”,那么例如减去最接近的整数并查看绝对值是否小于某个 epsilon(例如 0.00001)是一个不错的选择。

    【讨论】:

    • 我明白你的意思,但我认为在我检查的数字范围内,创建一个适用于所有情况的测试是半不可能的。我想我要做的是看看我是否可以重新设计它以完全避免浮动。
    【解决方案2】:

    如果您发现浮点数不准确,您可以使用 .NET 的 decimal 数据类型(它能够表示以 10 为基数表示的所有数字)对性能造成影响。除此之外,使用更高的精度 (double) 或整数数学。

    【讨论】:

      【解决方案3】:

      我同意 Brian 的观点,即依赖精确的浮点表示是危险的,但我无法重现您的问题。对我来说,droot 81.0 给出了0.0 的预期结果。你使用的是什么版本的 F#?您是在 .NET 还是 Mono 上运行?

      【讨论】:

      • 我都试过了。唯一的区别是问题从哪里开始。在 .net 上,它在 216 上开始表现得很有趣。在 mono 上,它在 81 上开始表现得很有趣。mono 和 .net 都有相同的问题,它们使用此代码返回错误的模数。我正在使用 F# 1.9.6.16
      • 是的,问题是 (216.0 ** (1.0 / 3.0)) 给出 5.9999999999999991... 然后模数运算符给出 0.9...,显示为 1.0。您可以通过进行简单的相等比较来向自己证明它实际上不是 1.0。不幸的是,您需要想出一种更可靠的方法来计算您想要的结果。
      • 我看不出 216 的立方根如何返回为 5.9999999...1。我想我将不得不深入研究 .Net 如何进行浮点数学运算,看看我能从中学到什么。
      • 这不是“.Net 如何进行浮点数学运算”,而是“浮点数学运算”。 1.0 / 3.0 不能用有限的二进制数字精确表示,值总是会有点偏差。
      猜你喜欢
      • 1970-01-01
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2016-02-22
      • 1970-01-01
      • 1970-01-01
      • 2012-12-18
      相关资源
      最近更新 更多