Добрый день.
Решил сокращать дроби, деля их на простые числа от 2 до минимального значения между числителем и знаменателем (т.е. если числитель больше знаменателя, то берём все простые числа от 2 до знаменателя, и наоборот).
Нахождение простых чисел реализовал через "Решето Эратосфена". Все найденные простые числа остаются в массиве simpleNumbers, в целях оптимизации, т.к. функция сокращения дроби используется многократно.
var simpleNumbers = [2, 3];
function getSimpleNumbers(limit) {
var i = (simpleNumbers.length == 0) ? 0 : simpleNumbers[ simpleNumbers.length - 1 ];
if( i > limit ) {
for (var k = 0; ; k++) {
if( simpleNumbers[k] > limit ) {
return simpleNumbers.slice(0, k);
break;
}
}
}
for (; i <= limit; i++) {
var flag = true;
for (var j = 0; j < simpleNumbers.length; j++) {
if( i % simpleNumbers[j] == 0 ) {
flag = false;
break;
}
}
if( flag ) {
simpleNumbers.push(i);
}
}
return simpleNumbers;
}
// Функция принимает два аргумента и максимально сокращает их.
// Функция возвращает объект с двумя свойствами n и d (числитель и знаменатель)
function reduceFrac(numerator, denomerator) {
var frac = {
n: numerator,
d: denomerator
}, s;
if(Math.abs(frac.n) > Math.abs(frac.d)) {
s = getSimpleNumbers( Math.abs(frac.d) );
} else {
s = getSimpleNumbers( Math.abs(frac.n) );
}
for (var i = 0; i < s.length; i++) {
while(true) {
if( Math.abs(frac.n % s[i]) == 0 && Math.abs(frac.d % s[i]) == 0 ) {
frac.n /= s[i];
frac.d /= s[i];
} else {
break;
}
}
}
return frac;
}