2011-01-10 2 views

ответ

54
// Reduce a fraction by finding the Greatest Common Divisor and dividing by it. 
function reduce(numerator,denominator){ 
    var gcd = function gcd(a,b){ 
    return b ? gcd(b, a%b) : a; 
    }; 
    gcd = gcd(numerator,denominator); 
    return [numerator/gcd, denominator/gcd]; 
} 

reduce(2,4); 
// [1,2] 

reduce(13427,3413358); 
// [463,117702] 
+2

Это очень элегантная функция 'gcd'. Единственное изменение, которое я бы предложил, - это некоторая форма проверки ввода для 'NaN' как' gcd (NaN, 1) 'производит' 1', где я ожидал бы «NaN» или ошибку. – zzzzBov

+2

@zzzzBov Интересный крайный кейс. Конечно, можно добавить 'if (isNaN (числитель) || isNaN (знаменатель)) возвращает NaN;' как первую строку. – Phrogz

+1

Замечательный факт, это решение использует алгоритм Евклида для поиска GCD: https://en.wikipedia.org/wiki/Euclidean_algorithm – camou

7

Нет, но вы можете написать один самостоятельно довольно легко. По существу вам нужно разделить верхнюю и нижнюю части фракции на их «Величайший общий знаменатель» ... Который вы можете рассчитать по алгоритму Евклида.

Читайте здесь для получения дополнительной информации: http://www.jimloy.com/number/euclids.htm

редактировать:

код (потому что все, кажется, делают это, это не использует рекурсию, хотя)

var FractionReduce = (function(){ 
    //Euclid's Algorithm 
    var getGCD = function(n, d){ 
     var numerator = (n<d)?n:d; 
     var denominator = (n<d)?d:n;   
     var remainder = numerator; 
     var lastRemainder = numerator; 

     while (true){ 
      lastRemainder = remainder; 
      remainder = denominator % numerator; 
      if (remainder === 0){ 
       break; 
      } 
      denominator = numerator; 
      numerator = remainder; 
     } 
     if(lastRemainder){ 
      return lastRemainder; 
     } 
    }; 

    var reduce = function(n, d){ 
     var gcd = getGCD(n, d); 

     return [n/gcd, d/gcd]; 
    }; 

    return { 
      getGCD:getGCD, 
      reduce:reduce 
      }; 

}()); 

alert(FractionReduce.reduce(3413358, 13427)); 
+0

+1 для обработки числителя> знаменатель – Phrogz

5

К уменьшите долю, разделите числитель и знаменатель на Величайший общий фактор. Phrogz и David уже предоставили исходный код.

Однако, если вы ищете библиотеки javascript для обработки фракций, то вот несколько на выбор.

  1. Fraction.js
  2. Math.Rational
  3. Ratio.js
  4. Rational.js

Вот пример использования Ratio.js.

var a = Ratio(2,4); 

a.toString() == "2/4"; 
a.simplify().toString() == "1/2"; // reduce() returns a clone of the Ratio() 
a.toString() == "2/4"; // Ratio functions are non-destructive. 
+0

Полезно, спасибо. Я разместил вопрос о относительной эффективности этих библиотек здесь: http: // stackoverflow.com/questions/15840390/what-is-the-most-efficient-fraction-library-in-javascript? noredirect = 1 # comment22538987_15840390 – Omn

+1

@Omn Итак, вы уже профиль производительности с помощью jsperf.com? Если вы видите какие-либо проблемы с Ratio.js, когда просто открываете билет, я попытаюсь его исправить. https://github.com/LarryBattle/Ratio.js –

+0

У меня нет опыта создания и запуска тестов. Я просто перешел в код и посмотрел на то, что, казалось, улучшило кодирование, комментарии и реализованные функции. Я закончил работу с Ratio.js, но с тех пор у меня не было возможности работать над этим проектом. Я обязательно сообщу, найду ли я какие-либо проблемы, и я могу внести исправления ошибок, если сам увижу проблему. – Omn

1

Я знаю, что уже есть ответ, но я хочу поделиться библиотекой JS, что я нашел, когда я искал что-то десятичные числа преобразовывают на фракцию и восстанавливающих фракции.

Библиотека звонит Fraction.js, что было действительно полезно для меня и сэкономило много времени и работы. Надеюсь, это может быть очень полезно кому-то еще!

0

Рекурсивная функция, использующая сокращение ECMAScript 6. Он работает для большинства фракций, пока остаток не слишком мал. 0 было переопределено, чтобы заставить его работать с массивами типа [1.2, 2.4, 12, 24]. Я тестировал в Chrome и IE Edge, чтобы он мог вести себя по-другому в других браузерах или обновлениях. Поэтому он должен работать с массивом поплавков.

Array.prototype.gcd = function() { 
    if (this.length === 0) 
    return null; 
    return this.reduce((prev, curr) => { 
    if (curr <= 1.00000000001e-12) 
     return prev 
    else 
     return [curr, prev % curr].gcd(); 
    }); 
    } 

    var reducedValueGCD = [1.2, 2.4, 12, 24, 240].gcd(); 

Поиск сокращения MDN или более информации here.

 Смежные вопросы

  • Нет связанных вопросов^_^