用于将小数转换为“漂亮”分数的优化算法

时间:2011-01-13 03:19:38

标签: algorithm decimal readability fractions

不是将任意小数转换为精确分数(类似于323527/4362363),而是试图将其转换为常见的易于识别的(就人类可读性而言)数量,如1 / 2,1 / 4, 1/8等

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

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

5 个答案:

答案 0 :(得分:7)

查找“连续分数近似”。维基百科在其“续篇”文章中有一个基本的介绍,但有一些优化的算法可以在生成分数时生成近似值。

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

答案 1 :(得分:3)

你可以使用欧几里德算法在枚举数和分母之间得到最大公约数,并用它除以它们。

答案 2 :(得分:0)

在下文中,我将假设我们的小数位于0和1之间。应该可以直接将其调整为较大的数字和负数。

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

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

答案 3 :(得分:0)

这是一个建议:假设你的起始分数是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)

  5. 通常情况下,1000的所有分母都具有人类可读性。

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

答案 4 :(得分:0)

非常愚蠢的解决方案,仅用于“预览”分数:

factor = 1/decimal
result = 1/Round(factor)
mult = 1

while (result = 1) {
  mult = mult * 10
  result = (1 * mult)/(Round(mult * factor))
}

result = simplify_with_GCD(result)
祝你好运!