【问题标题】:Performant algorithm to rationalize floats使浮点数合理化的高性能算法
【发布时间】:2012-04-02 16:59:11
【问题描述】:

给定一个浮点数,我希望得到一个近似小数的有理数的String 表示(在给定的容差 ε 内是可以的)。我目前的做法如下:

String rationalize(double d)
{
    String s = Double.toString(d);
    s = s.substring(s.indexOf('.')+1, s.length());
    return s + " / " + ApintMath.pow(new Apint(10), s.length()).toString();
}

如果您不熟悉它,ApintMath.pow 甚至可以处理任意长的数字,这很好,因为我正在尝试转换具有数千个小数位的小数。我的算法的性能很糟糕。

我将此归因于两件事,但可能还有更多:

  1. 我获取分数的方法非常幼稚。我确信有更好的方法。
  2. 分数未简化,因此使用该分数进行的任何后续计算都可能会浪费大量时间。

你会怎么做?是否还有其他我没有谈到的领域让我放慢了脚步?

【问题讨论】:

标签: java floating-point rational-numbers


【解决方案1】:

here 显示了一个 Stern–Brocot tree 实现,但您必须进行分析才能看到哪个更好。

附录:我在线性系统中使用org.jscience.mathematics.number.Rational 得到了很好的结果; org.apache.commons.math.fraction.BigFractiondouble 提供了几个可能有用的构造函数。对未定义的值都抛出合适的异常。

【讨论】:

  • 不幸的是,我用于有理数的库在尝试构造 1/0 时抛出异常。
  • 我不熟悉那个库,但这听起来是正确的做法。我在上面引用了一些替代方案。
  • 解决了这个问题——使用了 Stern-Brocot 树,但缩小了范围,因为我知道我不会有高于或低于某些值的有理数。感谢您的建议。
  • 好主意。仔细看,我看到这个Rational 忽略了一个零分母,使用Rational(1/0) 作为正无穷大。
  • 其他阅读本文的人请注意:Stern-Brocot 树并不比我在上面发布的算法快,因为他们得出答案的速度更慢。但是,它们生成的分数更小,计算速度更快,至少对于我的应用程序而言。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 2023-03-30
相关资源
最近更新 更多