例如,如果我的函数被称为getlowestfraction()
,那么这就是我期望的:
getlowestfraction(0.5) // returns 1, 2 or something along the lines of that
另一个例子:
getlowestfraction(0.125) // returns 1, 8 or something along the lines of that
答案 0 :(得分:6)
使用Continued Fractions可以有效地创建(有限或无限)分数 h n / k n 的序列给定实数 x 的任意良好近似值。
如果 x 是有理数,则过程在某个时刻停止, h n / k n == x < / em>的。如果 x 不是有理数,则序列 h n / k n ,n = 0,1,2,.. 。非常快地收敛到 x 。
连续分数算法仅产生减少的分数(分母和分母是相对素数),分数在 有些人认为给定实数的“最合理的近似值”。
我不是一个JavaScript人(通常使用C编程),但我尝试使用以下JavaScript函数实现该算法。如果有愚蠢的错误,请原谅我。但我检查了这个功能,它似乎工作正常。
function getlowestfraction(x0) {
var eps = 1.0E-15;
var h, h1, h2, k, k1, k2, a, x;
x = x0;
a = Math.floor(x);
h1 = 1;
k1 = 0;
h = a;
k = 1;
while (x-a > eps*k*k) {
x = 1/(x-a);
a = Math.floor(x);
h2 = h1; h1 = h;
k2 = k1; k1 = k;
h = h2 + a*h1;
k = k2 + a*k1;
}
return h + "/" + k;
}
当有理逼近精确或具有给定精度eps = 1.0E-15
时,循环停止。当然,您可以根据需要调整精度。 (while
条件来源于连续分数理论。)
示例(使用while循环的迭代次数):
getlowestfraction(0.5) = 1/2 (1 iteration)
getlowestfraction(0.125) = 1/8 (1 iteration)
getlowestfraction(0.1+0.2) = 3/10 (2 iterations)
getlowestfraction(1.0/3.0) = 1/3 (1 iteration)
getlowestfraction(Math.PI) = 80143857/25510582 (12 iterations)
请注意,此算法会将1/3
作为x = 1.0/3.0
的近似值。将x
重复乘以10的幂并取消常见因子会得到类似3333333333/10000000000
的内容。
以下是不同精度的示例:
eps = 1.0E-15
,您获得getlowestfraction(0.142857) = 142857/1000000
。eps = 1.0E-6
,您获得getlowestfraction(0.142857) = 1/7
。答案 1 :(得分:1)
你可以保持乘以10,直到你的分子和分母有整数值,然后使用this question的答案将分数减少到最简单的条件。
答案 2 :(得分:1)
请尝试使用此程序:
function toFrac(number) {
var fractional = number % 1;
if (fractional) {
var real = number - fractional;
var exponent = String(fractional).length - 2;
var denominator = Math.pow(10, exponent);
var mantissa = fractional * denominator;
var numerator = real * denominator + mantissa;
var gcd = GCD(numerator, denominator);
denominator /= gcd;
numerator /= gcd;
return [numerator, denominator];
} else return [number, 1];
}
function gcd(numerator, denominator) {
do {
var modulus = numerator % denominator;
numerator = denominator;
denominator = modulus;
} while (modulus);
return numerator;
}
然后您可以按如下方式使用它:
var start = new Date;
var PI = toFrac(Math.PI);
var end = new Date;
alert(PI);
alert(PI[0] / PI[1]);
alert(end - start + " ms");
您可以在此处查看演示:http://jsfiddle.net/MZaK9/1/
答案 3 :(得分:0)
只是摆弄代码,并自己得到答案:
function getlowestfraction (num) {
var i = 1;
var mynum = num;
var retnum = 0;
while (true) {
if (mynum * i % 1 == 0) {
retnum = mynum * i;
break;
}
// For exceptions, tuned down MAX value a bit
if (i > 9000000000000000) {
return false;
}
i++;
}
return retnum + ", " + i;
}
如果有人需要它。
P.S:我不是要展示我的专业知识或知识范围。我确实花了很长时间在JSFiddle试图解决这个问题(不管怎么说都不是很长时间)。答案 4 :(得分:0)
为简单起见,假设数字为x = 0 . ( a_1 a_2 ... a_k ) ( a_1 a_2 ... a_k ) ....
(请记住,前几个数字可能不适合重复模式,我们需要一种方法来确定k
是什么)。如果b
是基础,那么
b ^ k * x - x = ( b ^ k - 1 ) * x
一方面,但
b ^ k * x - x = ( a_1 a_2 ... a_k )
另一方面,(确切地说,这是一个整数)。
所以
x = ( a_1 ... a_k ) / ( b ^ k - 1 )
现在你可以使用Euclid的算法来获取gcd并将其除去以获得减少的分数。
你仍然需要弄清楚如何确定重复序列。这个问题应该有答案。编辑 - 一个答案:如果与模式\1
匹配,则为/([0-9]+)\1+$/
的长度(您可能希望在匹配舍入的bc之前丢弃最后一个数字)。如果没有匹配,则没有比“平凡”表示更好的“答案”(x * base ^ precision / base ^ precision)。
N.B。这个答案会对您对答案的期望做出一些假设,可能不适合您的需求。但它是从重复的十进制表示中再现分数的“教科书”方式 - see e.g. here