1
function gcd(a, b) {
    return (b) ? gcd(b, a % b) : a;
}
var dec2Frac = function (d) {
    var top = d.toString().replace(/\d+[.]/, '');
    var bot = Math.pow(10, top.length);
    if (d > 1) {
        top = +top + Math.floor(d) * bot;
    }
    var x = gcd(top, bot);
    var r1 = top / x;
    var r2 = bot / x;
    var frac =  r1 + "/" + r2;
    var parts = frac.split('/');
    var simpler = parts[0][0]+'/'+parts[1][0];
    return simpler;
};

如果我输入640x960=0.66666666666667

我希望结果在2/3这里很明显:http: //www.mindspring.com/~alanh/fracs.html

相反,此函数返回6/1. 在这里测试:http: //jsbin.com/asoxud/1/

4

2 回答 2

1

作为 MvG 答案的补充,

我发现这很有趣,并想了解浮点数是如何存储的,以及如何取回浮点数的一小部分来进行计算。

试图自己解决这个问题让我有点头疼,但是当它发出咔嗒声时,我想出了这个Fraction功能,

我不知道这是否对你有帮助,但是

既然已经写好了,何不留在这里

function Fraction(n, d) {
    if ("number" !== typeof n)
        throw new TypeError("Excptected Parameter to be of type number");

    var strings = n.toString(2).split("."); //Split the number by its decimal point 

    if (strings.length > 1 && !d) { //No denominator given and n is a float

        var floats = [strings[1].substr(0, 27), strings[1].substr(27, 54)]; //Split into to parts 

        var int64 = [
            parseInt(floats[0], 2) << 1,
            parseInt(floats[1], 2) << 1
        ];

        var denominator = Math.pow(2, strings[1].length + 1); //
        var numerator = int64[0] * Math.pow(2, floats[1].length);

        numerator += int64[1];
        numerator += parseInt(strings[0], 2) * denominator;

        this.numerator = numerator;
        this.denominator = denominator;
        this.reduce();

        this.approx = approx(n);

    } else if (strings.length < 2 && !d) { // If no denominator and n is an int 
        this.numerator = n;
        this.denominator = 1;
    } else { //if n and d
        this.numerator = n;
        this.denominator = d;
    }

    function approx(f, n) {
        n = n || 0;
        var fraction = new Fraction(1, 1);

        var float = Math.pow(f, -1);
        var rec = ~~float;
        var decimal = float - rec;

        if (float.toPrecision(Fraction.precision) == rec)
            return new Fraction(1, rec);
        var _fraction = approx(decimal, n + 1);

        fraction.denominator = rec * _fraction.denominator + _fraction.numerator;
        fraction.numerator = _fraction.denominator;

        return fraction;

    }

}

//The approx precision
Fraction.precision = 10;
Fraction.prototype.toString = function () {
    return this.numerator + "/" + this.denominator;
};
Fraction.prototype.gcd = function () {
    return (function gcd(u, v) {
        return ((u > 0) ? gcd(v % u, u) : v);
    })(this.numerator, this.denominator);
};
Fraction.prototype.reduce = function () {
    var _gcd = this.gcd();
    this.numerator /= _gcd;
    this.denominator /= _gcd;
};

Fraction.prototype.valueOf = function () {
    return this.numerator / this.denominator;
};




var f = new Fraction(0.3333); 
+ f; //0.3333333333
f.toString(); // 6004799502560181/18014398509481984 
+ f.approx //0.33333
+ f.approx.toString() //3333/10000

var g = new Fraction(2 / 3); 
+ g; //0.6666666666666666
g.toString(); //6004799503160661/9007199254740992
+ g.approx //0.6666666666666666
+ g.approx.toString() //2/3

这里还有一个JSbin

于 2013-05-03T18:42:41.370 回答
0

您的浮点数是您希望的有理数的近似值。参见例如浮点数学是否损坏?有关这方面的详细信息。结果是:您不能希望真正找到代表原始分数的分子和分母。

如果你想要那个分数,你应该看看连续分数。每个截断的连分数将代表任意值的最佳可能有理逼近。您可以继续此操作,直到错误足够小。

是一个可视化此近似值的页面。文本是德文的,但数学应该足够清楚。这个页面是英文的,但没有太多的可视化。

于 2013-05-02T13:20:38.247 回答