@DarCKoder

Как можно оптимизировать алгоритм сокращения дроби?

Добрый день.

Решил сокращать дроби, деля их на простые числа от 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;
}
  • Вопрос задан
  • 1437 просмотров
Пригласить эксперта
Ответы на вопрос 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Бинарный алгоритм вычисления наибольшего общего делителя (НОД)

function nod(m, n) {
  var mult = 0;
  while (true) {
    if (0 == m) {
      return n << mult;
    }
    if (0 == n) {
      return m << mult;
    }
    if (1 == m || 1 == n) {
      return 1 << mult;
    }
    if (m == n) {
      return m << mult;
    }
    if (0 == (m & 1) && 0 == (n & 1)) {
      mult++;
      m >>= 1;
      n >>= 1;
    } else if (0 == (m & 1)) {
      m >>= 1;
    } else if (0 == (n & 1)) {
      n >>= 1;
    } else if (m > n) {
      m = (m-n) >> 1;
    } else {
      n = (n-m) >> 1;
    }
  }
}

function reduceFrac(numerator, denomerator) {
  var divider = nod(numerator, denomerator);
  return {n: numerator/divider, d: denomerator/divider};
}
Ответ написан
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
Классическое решение -- поиск НОД алгоритмом Евклида.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы