Convert a decimal number to a fraction / rational number

前端 未结 11 1834
情歌与酒
情歌与酒 2020-12-01 16:36

In JavaScript, is there any way to convert a decimal number (such as 0.0002) to a fraction represented as a string (such as \"2/10000\")?

I

11条回答
  •  鱼传尺愫
    2020-12-01 17:19

    I used this site http://mathforum.org/library/drmath/view/51886.html to build a function but as the article mentions you will get an unreasonable large number for radicals or pi.

    Hope it helps though.

    function Fraction(){}
    Fraction.prototype.convert = function(x, improper)
    {
        improper = improper || false;
        var abs = Math.abs(x);
        this.sign = x/abs;
        x = abs;
        var stack = 0;
        this.whole = !improper ? Math.floor(x) : 0;
        var fractional = !improper ? x-this.whole : abs;
        /*recursive function that transforms the fraction*/
        function recurs(x){
            stack++;
            var intgr = Math.floor(x); //get the integer part of the number
            var dec = (x - intgr); //get the decimal part of the number
            if(dec < 0.0019 || stack > 20) return [intgr,1]; //return the last integer you divided by
            var num = recurs(1/dec); //call the function again with the inverted decimal part
            return[intgr*num[0]+num[1],num[0]]
        }
        var t = recurs(fractional); 
        this.numerator = t[0];
        this.denominator = t[1];
    }
    
    Fraction.prototype.toString = function()
    {
        var l  = this.sign.toString().length;
        var sign = l === 2 ? '-' : '';
        var whole = this.whole !== 0 ? this.sign*this.whole+' ': sign;
        return whole+this.numerator+'/'+this.denominator;
    }
    
    //var frac = new Fraction()
    //frac.convert(2.56, false)
    //console.log(frac.toString())
    //use frac.convert(2.56,true) to get it as an improper fraction
    

    If you just want a self-contained function that only returns the numerator and denominator then use the function below.

    var toFraction = function (dec) {
        var is_neg = dec < 0;
        dec = Math.abs(dec);
        var done = false;
        //you can adjust the epsilon to a larger number if you don't need very high precision
        var n1 = 0, d1 = 1, n2 = 1, d2 = 0, n = 0, q = dec, epsilon = 1e-13;
        while (!done) {
            n++;
            if (n > 10000) {
                done = true;
            }
            var a = parseInt(q);
            var num = n1 + a * n2;
            var den = d1 + a * d2;
            var e = (q - a);
            if (e < epsilon) {
                done = true;
            }
            q = 1 / e;
            n1 = n2;
            d1 = d2;
            n2 = num;
            d2 = den;
            if (Math.abs(num / den - dec) < epsilon || n > 30) {
                done = true;
            }
        }
        return [is_neg ? -num : num, den];
    };
    //Usage:
    //var frac = toFraction(0.5);
    //console.log(frac)
    //Output: [ 1, 2 ]
    

提交回复
热议问题