【问题标题】:Optimized algorithm for converting a decimal to a "pretty" fraction将小数转换为“漂亮”分数的优化算法
【发布时间】:2011-01-13 03:19:37
【问题描述】:

我没有将任意小数转换为精确分数(例如 323527/4362363),而是尝试转换为常见的易于识别(就人类可读性而言)的数量,例如 1/2、1/4、 1/8 等。

除了使用一系列 if-then、小于/等于等比较之外,还有更优化的技术可以做到这一点吗?

编辑:在我的特殊情况下,近似值是可以接受的。这个想法是 0.251243 ~ 0.25 = 1/4 - 在我的用例中,这“足够好”,就快速指标而言,后者更适合人类可读性(不用于计算,仅用作显示数字)。

【问题讨论】:

  • 您的问题含糊不清。你如何定义人类可读性?更重要的是,如果没有人类可读的等效形式怎么办?你允许近似值吗?我个人认为没有任何简单的方法可以在不求助于近似值的情况下以人类可读的形式编写示例 323526/4362363。
  • 近似值是可以接受的 - 4 位小数精度已经足够了
  • “人类可读”还有其他的东西,只是两个数字的长度。一般来说,“1/x”形式的分数是easy,但“4/85”很奇怪,最好用“1/41”表示。当然,“1/x”系列只适用于小于 0.5 的数字,而使用 0.4 的近似值意味着很大的损失……也许百分比表示就足够了?
  • (整数) + x/y 其中 x 和 y 均小于 10

标签: algorithm decimal readability fractions


【解决方案1】:

查找“连分数逼近”。 Wikipedia 在其“连分数”一文中有基本介绍,但有优化算法在生成分数的同时生成近似值。

然后选择一些停止启发式方法,即分母大小和近似值的组合,当您“足够接近”时。

【讨论】:

    【解决方案2】:

    您可以使用欧几里得算法得到枚举数和分母之间的最大公约数并除以它。

    【讨论】:

    • 我还建议您将分母限制在合理的范围内,以避免出现 107842/1454121 之类的情况(这是您的示例,已减少)。
    • mea culpa - 打错了那个初始分数...意思是 7 而不是 6 ;-)
    • 人们为什么要投票?这根本不能回答问题。他问的是如何将小数近似为简单分数,而不是关于减少分数。
    • 你说得对,在对问题进行编辑后,我的回答没有意义。
    【解决方案3】:

    在下文中,我将假设我们的小数介于 0 和 1 之间。将其应用于更大的数字和负数应该很简单。

    可能最简单的做法是选择您认为可接受的最大分母,然后创建一个介于 0 和 1 之间的分数列表,这些分数的分母小于或等于它们。一定要避免任何可以简化的分数。显然,一旦你列出了 1/2,你就不需要 2/4。您可以通过检查分子和分母的 GCD 是否为 1 来使用 Euclid 算法来避免可以简化的分数。一旦你有了你的清单。将它们评估为浮点数(可能是双精度数,但数据类型显然取决于您选择的编程语言)。然后将它们插入到平衡二叉搜索树中,该树存储原始分数和分数的浮点评估。您应该只需要执行一次即可进行初始设置,因此 n*log(n) 时间(其中 n 是分数的数量)不会太多。

    然后,每当您获得一个数字时,只需搜索树以在搜索树中找到最接近它的数字。请注意,这比搜索精确匹配稍微复杂一些,因为您要查找的节点可能不是叶节点。因此,当您遍历树时,请记录您访问过的最近的值节点。一旦到达叶节点并将其与您访问过的最接近的值节点进行比较,您就完成了。无论您最接近哪一个,它的分数就是您的答案。

    【讨论】:

      【解决方案4】:

      这里是一个建议:假设你的起始分数是 p/q

      1. 将 r = p/q 计算为有理数(浮点)值(例如 r = float(p)/float(q))

      2. 计算四舍五入的小数 x = int(10000*r)

      3. 计算 x 和 10000 的 GCD(最大公分母):s = GCD(x, 10000)

      4. 将结果表示为 m / n,其中 m = x/s 和 n = y/s(您的示例计算为 371 / 5000)

      通常,1000 的所有分母都是人类可读的。

      当值更接近更简单的情况(例如 1/3)时,这可能不会提供最佳结果。但是,我个人发现 379/1000 比 47/62(这是最短的分数表示)更具人类可读性。不过,您可以添加一些例外来微调此类过程(例如,计算 p/GCD(p,q) 、 q/GCD(p,q) 并在其中一个是单个数字值时接受它,然后再继续此方法)

      【讨论】:

        【解决方案5】:

        相当愚蠢的解决方案,仅用于“预览”部分:

        因子 = 1/小数 结果 = 1/轮(因子) 乘数 = 1 而(结果= 1){ 乘数 = 乘数 * 10 结果 = (1 * mult)/(Round(mult * factor)) } 结果 = 简化_with_GCD(结果)

        祝你好运!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-03-15
          • 1970-01-01
          • 1970-01-01
          • 2011-07-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多