Javascript 将十进制数转换为分数/有理数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14783869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert a decimal number to a fraction / rational number
提问by Anderson Green
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")?
在 JavaScript 中,有没有办法将十进制数(例如0.0002)转换为表示为字符串的分数(例如 " 2/10000")?
If a function called decimalToFractionhad been written for this purpose, then decimalToFraction(0.0002)would return the string "2/10000".
如果decimalToFraction为此目的编写了一个被调用的函数,decimalToFraction(0.0002)则将返回 string "2/10000"。
回答by Trent Earl
You can use Erik Garrison's fraction.jslibrary to do that and more fractional operations.
您可以使用 Erik Garrison 的fraction.js库来执行该操作以及更多的分数运算。
var f = new Fraction(2, 10000);
console.log(f.numerator + '/' + f.denominator);
To to do .003 you can just do
要做 0.003 你可以做
var f = new Fraction(.003);
console.log(f.numerator + '/' + f.denominator);
回答by Alex Wayne
A little googling with the term "decimal to fraction js"the first yielded this:
有一点与术语“小数部分JS”谷歌搜索的第一产生这样的:
http://wildreason.com/wildreason-blog/2010/javascript-convert-a-decimal-into-a-simplified-fraction/
http://wildreason.com/wildreason-blog/2010/javascript-convert-a-decimal-into-a-simplified-fraction/
It seems to work:
它似乎有效:
function HCF(u, v) {
var U = u, V = v
while (true) {
if (!(U%=V)) return V
if (!(V%=U)) return U
}
}
//convert a decimal into a fraction
function fraction(decimal){
if(!decimal){
decimal=this;
}
whole = String(decimal).split('.')[0];
decimal = parseFloat("."+String(decimal).split('.')[1]);
num = "1";
for(z=0; z<String(decimal).length-2; z++){
num += "0";
}
decimal = decimal*num;
num = parseInt(num);
for(z=2; z<decimal+1; z++){
if(decimal%z==0 && num%z==0){
decimal = decimal/z;
num = num/z;
z=2;
}
}
//if format of fraction is xx/xxx
if (decimal.toString().length == 2 &&
num.toString().length == 3) {
//reduce by removing trailing 0's
decimal = Math.round(Math.round(decimal)/10);
num = Math.round(Math.round(num)/10);
}
//if format of fraction is xx/xx
else if (decimal.toString().length == 2 &&
num.toString().length == 2) {
decimal = Math.round(decimal/10);
num = Math.round(num/10);
}
//get highest common factor to simplify
var t = HCF(decimal, num);
//return the fraction after simplifying it
return ((whole==0)?"" : whole+" ")+decimal/t+"/"+num/t;
}
// Test it
alert(fraction(0.0002)); // "1/5000"
回答by jiggzson
I used this site http://mathforum.org/library/drmath/view/51886.htmlto build a function but as the article mentions you will get an unreasonable large number for radicals or pi.
我使用这个网站http://mathforum.org/library/drmath/view/51886.html来构建一个函数,但正如文章中提到的,你会得到一个不合理的大量偏旁或 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 ]
回答by WalterDa
Very old question but maybe someone can find this useful. It's iterative, not recursive and doesn't require factorization
很老的问题,但也许有人会发现这很有用。它是迭代的,不是递归的,不需要因式分解
function getClosestFraction(value, tol) {
var original_value = value;
var iteration = 0;
var denominator=1, last_d = 0, numerator;
while (iteration < 20) {
value = 1 / (value - Math.floor(value))
var _d = denominator;
denominator = Math.floor(denominator * value + last_d);
last_d = _d;
numerator = Math.ceil(original_value * denominator)
if (Math.abs(numerator/denominator - original_value) < tol)
break;
iteration++;
}
return {numerator: numerator, denominator: denominator};
};
回答by Chemistree
There is a very simple solution using string representation of numbers
使用数字的字符串表示有一个非常简单的解决方案
string = function(f){ // returns string representation of an object or number
return f+"";
}
fPart = function(f){ // returns the fraction part (the part after the '.') of a number
str = string(f);
return str.indexOf(".")<0?"0":str.substring(str.indexOf(".") + 1);
}
wPart = function(f){ // returns the integer part (the part before the '.') of a number
str = string(f);
return str.indexOf(".")<0?str:str.substring(0, str.indexOf(".")); // possibility 1
//return string(f - parseInt(fPart(f))); // just substract the fPart
}
power = function(base, exp){
var tmp = base;
while(exp>1){
base*=tmp;
--exp;
}
return base;
}
getFraction = function(f){ // the function
var denominator = power(10, fPart(f).length), numerator = parseInt(fPart(f)) + parseInt(wPart(f))*denominator;
return "[ " + numerator + ", " + denominator + "]";
}
console.log(getFraction(987.23));
which will just check how many numbers are in the fraction and then expands the fraction of f/1 until f is an integer. This can lead to huge fractions, so you can reduce it by dividing both numerator and denominator by the greatest common divisor of both, e.g.
它只会检查分数中有多少个数字,然后扩展 f/1 的分数,直到 f 是一个整数。这可能会导致很大的分数,因此您可以通过将分子和分母除以两者的最大公约数来减少它,例如
// greatest common divisor brute force
gcd = function(x,y){
for(var i = Math.min(x, y);i>0;i--) if(!(x%i||y%i)) return i;
return 1;
}
回答by Popnoodles
The good news is that it's possible, but you'll have to convert it to code.
好消息是这是可能的,但您必须将其转换为代码。
Let's go with 2.56 for no reason at all.
让我们毫无理由地使用 2.56。
Use the decimal portion of the number .56
使用数字的小数部分 0.56
There are 2 digits in .56, write .56 as 56/100.
.56 中有 2 位数字,将 .56 写为 56/100。
So we have 2 + 56/100 and need to reduce this fraction to lowest terms by dividing both the numerator and denominator by the greatest common divisor, which is 4 in this case.
所以我们有 2 + 56/100 并且需要通过将分子和分母除以最大公约数(在本例中为 4)来将这个分数减少到最低项。
So, this fraction reduced to lowest terms is 2 + 14/25.
所以,这个分数减少到最低项是 2 + 14/25。
To add those whole 2, we multiply by the divisor and add to the 14
要将这些整数 2 相加,我们乘以除数并添加到 14
(2*25 + 14)/25 = 64/25
(2*25 + 14)/25 = 64/25
回答by hewstone
I did what popnoodles suggested and here it is
我按照popnoodles 的建议做了,结果就在这里
function FractionFormatter(value) {
if (value == undefined || value == null || isNaN(value))
return "";
function _FractionFormatterHighestCommonFactor(u, v) {
var U = u, V = v
while (true) {
if (!(U %= V)) return V
if (!(V %= U)) return U
}
}
var parts = value.toString().split('.');
if (parts.length == 1)
return parts;
else if (parts.length == 2) {
var wholeNum = parts[0];
var decimal = parts[1];
var denom = Math.pow(10, decimal.length);
var factor = _FractionFormatterHighestCommonFactor(decimal, denom)
return (wholeNum == '0' ? '' : (wholeNum + " ")) + (decimal / factor) + '/' + (denom / factor);
} else {
return "";
}
}
回答by Jabel Márquez
I just want a leave one alternative that I found to convert decimal numbers into fractionsand reducing fractions, it's a JS library.
我只想留下一个替代方案,我发现它可以将十进制数转换为分数并减少分数,它是一个 JS 库。
The library calls fraction.js, it was really helpful for me and save me a lot time and work. Hope can be useful to somebody else!
该库调用了fraction.js,它对我真的很有帮助,并为我节省了很多时间和工作。希望可以对其他人有用!
回答by RWolfe
This may be a little old but the code that was posted fails on 0 values I have fixed that error and will post the updated code below
这可能有点旧,但发布的代码在 0 值时失败我已修复该错误并将在下面发布更新的代码
//function to get highest common factor of two numbers (a fraction)
function HCF(u, v) {
var U = u, V = v
while (true) {
if (!(U%=V)) return V
if (!(V%=U)) return U
}
}
//convert a decimal into a fraction
function fraction(decimal){
if(!decimal){
decimal=this;
}
whole = String(decimal).split('.')[0];
decimal = parseFloat("."+String(decimal).split('.')[1]);
num = "1";
for(z=0; z<String(decimal).length-2; z++){
num += "0";
}
decimal = decimal*num;
num = parseInt(num);
for(z=2; z<decimal+1; z++){
if(decimal%z==0 && num%z==0){
decimal = decimal/z;
num = num/z;
z=2;
}
}
//if format of fraction is xx/xxx
if (decimal.toString().length == 2 &&
num.toString().length == 3) {
//reduce by removing trailing 0's
// '
decimal = Math.round(Math.round(decimal)/10);
num = Math.round(Math.round(num)/10);
}
//if format of fraction is xx/xx
else if (decimal.toString().length == 2 &&
num.toString().length == 2) {
decimal = Math.round(decimal/10);
num = Math.round(num/10);
}
//get highest common factor to simplify
var t = HCF(decimal, num);
//return the fraction after simplifying it
if(isNaN(whole) === true)
{
whole = "0";
}
if(isNaN(decimal) === true)
{
return ((whole==0)?"0" : whole);
}
else
{
return ((whole==0)?"0 " : whole+" ")+decimal/t+"/"+num/t;
}
}
回答by Samuel Williams
I know this is an old question, but I have created a function that has been greatly simplified.
我知道这是一个老问题,但我创建了一个大大简化的函数。
Math.fraction=function(x){
return x?+x?x.toString().includes(".")?x.toString().replace(".","")/(function(a,b){return b?arguments.callee(b,a%b):a;})(x.toString().replace(".",""),"1"+"0".repeat(x.toString().split(".")[1].length))+"/"+("1"+"0".repeat(x.toString().split(".")[1].length))/(function(a,b){return b?arguments.callee(b,a%b):a;})(x.toString().replace(".",""),"1"+"0".repeat(x.toString().split(".")[1].length)):x+"/1":NaN:void 0;
}
Call it with Math.fraction(2.56)
调用它 Math.fraction(2.56)
It will:
它会:
- return NaN if the input is not a number
- return undefined if the input is undefined
- reduce the fraction
- return a
string(useMath.fraction(2.56).split("/")for an array containing the numerator and denominator)
- 如果输入不是数字,则返回 NaN
- 如果输入未定义,则返回 undefined
- 减少分数
- 返回一个
string(Math.fraction(2.56).split("/")用于包含分子和分母的数组)
Please note that this uses the deprecated arguments.callee, and thus may be incompatible in some browsers.
请注意,这使用了已弃用的arguments.callee,因此在某些浏览器中可能不兼容。
Test it here
在这里测试

