【问题标题】:Convert a float to an approximate fraction in javascript在javascript中将浮点数转换为近似分数
【发布时间】:2013-10-16 03:19:55
【问题描述】:

我们需要将可能类似于 3.33333000540733337 的计算值转换为 3 1/3。我尝试过的任何库(例如https://github.com/peterolson/BigRational.js)都会将其转换为最准确的有理数,而我只关心近似有理数,即 0.01 有效小数。

在 ruby​​ 中,我们目前执行 Rational(1.333).rationalize(Rational(0.01)),它给我们 1 作为整数,1 作为分子,3 作为分母。

任何关于可能有帮助的算法的想法都会很棒。

【问题讨论】:

标签: javascript math decimal fractions


【解决方案1】:

在使用您的库之前使用.toFixed() 方法。见http://www.w3schools.com/jsref/jsref_tofixed.asp

【讨论】:

  • 作为 Peter cmets,这仍然无法满足我们的需求,因为我们需要 1/3 而不是 33/100
【解决方案2】:

您可以使用.toFixed() 来获得一个四舍五入的固定精度版本,然后将 BigRational 应用于该版本:

var n = 3.33333000540733337;
m = n.toFixed(2);       // 3.33

或者,.toPrecision() 将为指定的有效数字位数提供一个数字。

参考: .toFixed() .toPrecision()

【讨论】:

    【解决方案3】:

    是时候整理你的数学了。这确实是小学数学,但有点容易忘记。为什么要 3 1/3?

    您正在尝试将一个有理数(所有浮点数都是有理数)转换为另一个有理数(所有分数都是有理数)。

    所以选择你的分母。一切由此而来! (减少到最低限度 - 除非你想让自己看起来像从小学辍学。)

    【讨论】:

    • 我们正在显示配方数据,并将 3 汤匙面粉转换为 3 1/3 杯面粉。转换因子都以克为单位,所以我们知道一个非常精确的数字,但需要一个更近似的值。因此需要知道 3 1/3 而不是 3.33333333334 或类似的
    • 你没有抓住重点!为什么是 3 1/3 (10/3) 而不是 3.25 (13/4)、3.5 (7/2) 或 3.4 (17/5)?还是 3.3(330/100 降低到 33/10)?
    • 因为我们正在打印食谱,我们需要通用测量结果,而不是任何“过于精确”的结果
    • 即使你认为他没有抓住重点(顺便说一句,我没有),我认为你有点太居高临下了。您可以很好地解释这个概念,而无需告诉人们他们需要复习数学,以免他们看起来像小学辍学生。
    【解决方案4】:

    您可以通过 https://github.com/peterolson/BigRational.js 库使用这样的函数:

    function rationalize(rational, epsilon) {
        var denominator = 0;
        var numerator;
        var error;
    
        do {
            denominator++;
            numerator = Math.round((rational.numerator * denominator) / rational.denominator);
            error = Math.abs(rational.minus(numerator / denominator));
        } while (error > epsilon);
        return bigRat(numerator, denominator);
    }
    

    它将返回一个 bigRat 对象。你可以用这个检查你的例子:

    console.log(rationalize(bigRat(3.33333000540733337),0.01));
    

    【讨论】:

    • 谢谢,这似乎可以做到,我得写一些比较测试来看看它是否与我们从 ruby​​ 得到的匹配。
    • 这仅适用于 JavaScript Number 类型范围内的分子和分母,这可能足够也可能不够。如果您需要保留任意长度的分子和分母,您应该使用 BigRat 方法,如 numerator = BigRat(rational.numerator.times(denominator)).over(rational.denominator).round() 等。
    • @PeterOlson 我们很可能会处理小到足以在标准厨房食谱中使用的量,所以我怀疑我们是否超出了 Number 可以处理的范围,至少到目前为止作为小数点左边的数字,鉴于我们试图在某种意义上使小数点右边的数字不太精确,我认为这应该没问题。
    • 写了一个快速测试工具jsfiddle.net/cKEWS/3,它似乎工作得很好,除了 .3 它似乎无法达到 1/3,除非我将 epsilon 更改为 .1 而不是.01.
    • 没关系,3/10s 正是 ruby​​ lib 在那种情况下所显示的,所以看起来我们在那里也很好。这似乎很可能是赢家。
    【解决方案5】:

    我会再试一次。大概您将问题标记为“数学”。那么让我们来看看数学吧。

    1. 分数是有理数。
    2. 有理数都是 n 除以 m 的形式,(n / m),其中 n 和 m 是整数,m 不为零。
    3. 您需要“混合分数”。
    4. 在确定分母 (m) 之前,您不能期望“四舍五入到最接近的分数”,无论是整数还是混合。如果您选择 m = 100,那么您可以四舍五入到最接近的第 100 位。如果选择 1,则可以四舍五入到最接近的整数。 2 到最近的一半,等等。
    5. 现在您已经选择了分母,我们称之为 m,将您的值 (v) 乘以 m。
    6. 将结果四舍五入为最接近的整数,称为 rv。
    7. 混合分数的整个部分将是地板 (rv/m)。小数部分将是 (rv modulo m)/m (取模的意思是先除以二,取余数)

      示例 v = 3.45。

      你想把它四舍五入到最接近的 1/3,所以 m = 3

      rv = 舍入到最接近的整数 (3.45 * 3) = 舍入 (10.35) = 10

      整个部分 = 地板 (10/3) = 3

      小数部分 = (10 模 3) / 3 = 1/3

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-19
      • 1970-01-01
      • 2010-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多