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

时间:2014-05-09 23:02:13

标签: 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;

10 个答案:

答案 0 :(得分:12)

你的前两个步骤是合理的。

但你应该做的是分子和分母计算Greatest Common Divisor (GCD)然后用分数除以分子和分母得到你想要的分数。

GCD很容易计算。这是Euclid's algorithm

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

  return gcd(b, a % b);
};

修改

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

答案 1 :(得分:6)

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

下面的算法是一个如何解决这个问题的例子,但是,效率低下并且仅限于搜索高达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();
<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>

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

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

答案 2 :(得分:5)

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

的Javascript

var frac = new Fraction(0.3435);

console.log(frac.toString());

输出

687/2000

jsFiddle

答案 3 :(得分:2)

使用Euclidean algorithm查找最大公约数。

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];
}

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

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

reduce(13427,3413358);
// [463,117702]

因此,从已经拥有的东西开始,

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);

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

答案 4 :(得分:1)

一种快速简便的方法是

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

答案 5 :(得分:1)

我已经在整个网站上进行了研究,并且将所有代码组合为一个,接下来就可以了!

function fra_to_dec(num){
    var test=(String(num).split('.')[1] || []).length;
    var num=(num*(10**Number(test)))
    var den=(10**Number(test))
    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];
    }
    return (reduce(num,den)[0]+"/"+reduce(num,den)[1])
}

此代码非常易于使用!您甚至可以在此功能中输入数字

答案 6 :(得分:1)

这是我最快的。没有GCD。至少可以保留5个尾随小数点。

function decToFrac(n)
{
    let rcp = (n%1 == 0) ? 1: 1/(n%1);
    let den = rcp;
    const lim = 10;
    for (let i = 0; i < lim && Number.isInteger(Math.round(rcp * 10**(lim-i)) / 10**(lim-i)) != true; i++)
    {
        rcp = 1/(rcp%1);
        den *= rcp;
    }
    return [Math.round(n*den), Math.round(den)];
}

function impToProp(n, d)
{
    return [Math.floor(n/d), (n%d), d];
}

var dec = 3.141592;
var frac = decToFrac(dec); // improper
var prop = impToProp(frac[0], frac[1]); // proper

答案 7 :(得分:0)

棘手的一点是不要让浮点被带走。

将数字转换为字符串会限制尾随数字

特别是当你有一个带整数的小数时,比如1.0625。

您可以通过传递精度参数来舍入笨拙的分数。

通常你想强制一个舍入值向上,所以第三个参数可以指定。

(例如;如果您使用的是1/64的精度,非零数字的最小回报将是1/64,而不是0.)

Math.gcd= function(a, b){
    if(b) return Math.gcd(b, a%b);
    return Math.abs(a);
}
Math.fraction= function(n, prec, up){
    var s= String(n), 
    p= s.indexOf('.');
    if(p== -1) return s;

    var i= Math.floor(n) || '', 
    dec= s.substring(p), 
    m= prec || Math.pow(10, dec.length-1), 
    num= up=== 1? Math.ceil(dec*m): Math.round(dec*m), 
    den= m, 
    g= Math.gcd(num, den);

    if(den/g==1) return String(i+(num/g));

    if(i) i= i+' and  ';
    return i+ String(num/g)+'/'+String(den/g);
}

<强> Math.roundFraction(.3435,64);值:(字符串)11/32

答案 8 :(得分:0)

我在16日提出了这个问题

function getfract(theNum){
    var input=theNum.toString();
    var whole = input.split(".")[0];
    var rem = input.split(".")[1] * .1;
    return(whole + " " + Math.round(rem * 16) + "/16");
}

答案 9 :(得分:0)

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

例如,这是一个非常粗略的方法,它将小数点的一部分归零:

function toFraction(x, tollerance) {
    if (x < 0) x = -x;
    if (!tollerance) tollerance = 0.0001;
    var num = 1, den = 1;

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

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

    iterate();
    return [num, den];
}

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