将十进制数转换为javascript中的分数或最接近的分数

Muh*_*mer 6 javascript

所以我希望能够将任何十进制数转换为分数.在这两种形式中,例如没有剩余的形式,如:3/5或者余数:3 1/4.

我在做什么是这个..

假设我有号码.3435.

  • 计算小数后的位数.
  • 乘以数字前的数量乘以10.
  • 然后以某种方式找到最大的共同因素

现在我不知道如何找到GCF.而且我也不知道如何实现逻辑来找到代表数字的分数或者如果不存在精确分数则以其余形式表示.

我到目前为止的代码:(测试)

x = 34/35;
a = x - x.toFixed();
tens = (10).pow(a.toString().length - 2);

numerator = tens * x;
denominator = tens;
Run Code Online (Sandbox Code Playgroud)

San*_*nen 16

你的前两步是合理的.

但是你应该做的是分子和分母计算最大公约数(GCD)然后用分数除以分子和分母得到你想要的分数.

GCD很容易计算.这是欧几里德的算法:

var gcd = function(a, b) {
  if (!b) return a;

  return gcd(b, a % b);
};
Run Code Online (Sandbox Code Playgroud)

编辑

我添加了一个完全正常工作的JSFiddle.


Ste*_*uan 10

您可以对不同的分母使用强力测试并保留最小错误的结果.

下面的算法是一个如何解决这个问题的例子,但是,效率低下并且仅限于搜索高达10000的分母.

function find_rational(value, maxdenom) {
  var best = { numer: 1, denom: 1, err: Math.abs(value - 1) }
  if (!maxdenom) maxdenom = 10000;
  for (var denom = 1; best.err > 0 && denom <= maxdenom; denom++) {
    var numer = Math.round(value * denom);
    var err = Math.abs(value - numer / denom);
    if (err >= best.err) continue;
    best.numer = numer;
    best.denom = denom;
    best.err = err;
    console.log(best.numer + "/" + best.denom + "=" + (numer/denom) + " error " + best.err);
  }
  return best;
}
  
function calc() {
    var value = parseFloat($("#myInput").val());
    console.clear();
    console.log("Looking up " + value);
    if (isNaN(value)) {
        $("#myResult").val("NaN");
        return;
    }
    var rational = find_rational(value, 10000);
    $("#myResult").val(rational.numer + " / " + rational.denom);
}

calc();
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Input: <INPUT type="text" name="myInput" id="myInput" value=".3435" onkeyup="calc()"/>
Result: <INPUT name="myResult" id="myResult" value=""/>
<P>
Run Code Online (Sandbox Code Playgroud)

以上确定.3435为分数为687/2000.

另外,如果你把PI给了17位小数(3.14159265358979323),它会产生好看的分数,如22/7和355/113.

  • 我确实说这是低效的,但是,这是一个简单的答案. (3认同)
  • 这是实际的最佳答案!它可以正确地将`0.5555555555555555`转换成`“ 5/9”`。其他答案不能做到这一点。 (3认同)

小智 8

一种快速简便的方法是

getFraction = (decimal) => {
  for(var denominator = 1; (decimal * denominator) % 1 !== 0; denominator++);
  return {numerator: decimal * denominator, denominator: denominator};
}
Run Code Online (Sandbox Code Playgroud)


Xot*_*750 6

除非你愿意自己开发一些东西,否则我建议你使用一个已经付出努力的库,比如fraction.js

使用Javascript

var frac = new Fraction(0.3435);

console.log(frac.toString());
Run Code Online (Sandbox Code Playgroud)

产量

687/2000
Run Code Online (Sandbox Code Playgroud)

jsFiddle上


Deh*_*oos 5

使用欧几里得算法找到最大公约数。

function reduce(numerator,denominator){
  var gcd = function gcd(a,b){
    return b ? gcd(b, a%b) : a;
  };
  gcd = gcd(numerator,denominator);
  return [numerator/gcd, denominator/gcd];
}
Run Code Online (Sandbox Code Playgroud)

这将在您的控制台上为您提供以下结果

reduce(2,4);
// [1,2]

reduce(13427,3413358);
// [463,117702]
Run Code Online (Sandbox Code Playgroud)

所以通过继续你已经拥有的,

var x = 34/35;
var a = x - x.toFixed();
var tens = Math.pow(10,a.toString().length - 2);

var numerator = tens * x;
var denominator = tens;

reduce(numerator,denominator);
Run Code Online (Sandbox Code Playgroud)

来源:https : //stackoverflow.com/a/4652513/1998725


cho*_*wey 5

使用 GCD 方法我得到的结果很差。我使用迭代方法得到了更好的结果。

例如,这是一种非常粗略的方法,它对小数的分数进行归零:

function toFraction(x, tolerance) {
    if (x == 0) return [0, 1];
    if (x < 0) x = -x;
    if (!tolerance) tolerance = 0.0001;
    var num = 1, den = 1;

    function iterate() {
        var R = num/den;
        if (Math.abs((R-x)/x) < tolerance) return;

        if (R < x) num++;
        else den++;
        iterate();
    }

    iterate();
    return [num, den];
}
Run Code Online (Sandbox Code Playgroud)

这个想法是,如果您低于该值,则增加分子,如果高于该值,则增加分母。