Skip to content

Instantly share code, notes, and snippets.

@redteam-snippets
Created October 22, 2012 21:02
Show Gist options
  • Save redteam-snippets/3934258 to your computer and use it in GitHub Desktop.
Save redteam-snippets/3934258 to your computer and use it in GitHub Desktop.
JavaScript: Decimal To Fraction
// Adapted from: http://bateru.com/news/2011/11/improved-code-for-javascript-decimal-to-fraction/
function gcd(a, b) {
return (b) ? gcd(b, a % b) : a;
}
var decimalToFraction = function (_decimal) {
var top = _decimal.toString().replace(/\d+[.]/, '');
var bottom = Math.pow(10, top.length);
if (_decimal > 1) {
top = +top + Math.floor(_decimal) * bottom;
}
var x = gcd(top, bottom);
return {
top : (top / x),
bottom : (bottom / x),
display : (top / x) + ':' + (bottom / x)
};
};
@galeamark7
Copy link

Added support For int & negative numbers, further testing is needed to ensure it works in all scenarios

var decimalToFraction = function (_decimal) {
    if (_decimal == parseInt(_decimal)) {
        return {
            top: parseInt(_decimal),
            bottom: 1,
            display: parseInt(_decimal) + '/' + 1
        };
    }
    else {
        var top = _decimal.toString().includes(".") ? _decimal.toString().replace(/\d+[.]/, '') : 0;
        var bottom = Math.pow(10, top.toString().replace('-','').length);
        if (_decimal >= 1) {
            top = +top + (Math.floor(_decimal) * bottom);
        }
        else if (_decimal <= -1) {
            top = +top + (Math.ceil(_decimal) * bottom);
        }

        var x = Math.abs(gcd(top, bottom));
        return {
            top: (top / x),
            bottom: (bottom / x),
            display: (top / x) + '/' + (bottom / x)
        };
    }
};

@LumberJaxolotl
Copy link

For those of you who are coming here for a clean copy and paste, here is the final code @galeamark7:

function gcd(a, b) {
	return (b) ? gcd(b, a % b) : a;
}
var decimalToFraction = function (_decimal) {
    if (_decimal == parseInt(_decimal)) {
        return {
            top: parseInt(_decimal),
            bottom: 1,
            display: parseInt(_decimal) + '/' + 1
        };
    }
    else {
        var top = _decimal.toString().includes(".") ? _decimal.toString().replace(/\d+[.]/, '') : 0;
        var bottom = Math.pow(10, top.toString().replace('-','').length);
        if (_decimal >= 1) {
            top = +top + (Math.floor(_decimal) * bottom);
        }
        else if (_decimal <= -1) {
            top = +top + (Math.ceil(_decimal) * bottom);
        }

        var x = Math.abs(gcd(top, bottom));
        return {
            top: (top / x),
            bottom: (bottom / x),
            display: (top / x) + '/' + (bottom / x)
        };
    }
};

@DouglasLivingstone
Copy link

I was looking for something like the functions above, and ended up using this npm package: https://www.npmjs.com/package/fraction.js It builds on the idea of parsing a decimal into a fraction, then adds utilities like add, subtract, etc as well.

@AA-HABIB
Copy link

AA-HABIB commented Dec 31, 2020

Please use JS comments(// or /* */) because some of us who are inexperienced might want to learn how to do it, instead of copying and pasting.

@kheengz
Copy link

kheengz commented Jan 26, 2021

const toLowestFraction = (fraction, denominator = 100) => {
	const numerator = fraction * denominator;
	let gcd = (a, b) => {
		return b ? gcd(b, a % b) : a;
	};
	gcd = gcd(numerator, denominator);

	return [ numerator / gcd, numerator / gcd ];
};

// Usage
const [numerator, numerator] = toLowestFraction(0.123);

@acegilz
Copy link

acegilz commented Jul 5, 2021

You should include case for 1, otherwise it incorrectly returns "1/10"

var decimalToFraction = function (_decimal) {

	if (_decimal == 1){
		return {
			top		: 1,
			bottom	: 1,
			display	: 1 + ':' + 1
		};
	}  else {

		var top		= _decimal.toString().replace(/\d+[.]/, '');
		var bottom	= Math.pow(10, top.length);
		if (_decimal > 1) {
			top	= +top + Math.floor(_decimal) * bottom;
		}
		var x = gcd(top, bottom);
		return {
			top		: (top / x),
			bottom	: (bottom / x),
			display	: (top / x) + ':' + (bottom / x)
		};
	}
};

@tawanda-profuse
Copy link

This is by far the most effective solution

@greybeetle213
Copy link

It is wrong every time a whole number is inputted, so it should be:

function decimalToFraction(_decimal) {

	if (_decimal%1 == 0){
		return {
			top		: _decimal,
			bottom	: 1,
			display	: _decimal + ':' + 1
		};
	}  else {

		var top		= _decimal.toString().replace(/\d+[.]/, '');
		var bottom	= Math.pow(10, top.length);
		if (_decimal > 1) {
			top	= +top + Math.floor(_decimal) * bottom;
		}
		var x = gcd(top, bottom);
		return {
			top		: (top / x),
			bottom	: (bottom / x),
			display	: (top / x) + ':' + (bottom / x)
		};
	}
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment