2011-01-10 8 views

Respuesta

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

Es una función 'gcd' muy elegante. El único cambio que sugeriría es alguna forma de comprobación de entrada para 'NaN' como' gcd (NaN, 1) 'produce' 1' donde esperaría 'NaN' o un error. – zzzzBov

+2

@zzzzBov Un caso de borde interesante. Ciertamente, uno podría agregar 'if (isNaN (numerador) || isNaN (denominador)) return NaN;' como la primera línea. – Phrogz

+1

hecho de la diversión, esta solución usa el algoritmo de Euclides para encontrar GCD: https://en.wikipedia.org/wiki/Euclidean_algorithm – camou

7

No, pero puede escribir uno con bastante facilidad. Esencialmente necesitas dividir las partes superior e inferior de la fracción por su "Mayor denominador común" ... que puedes calcular a partir del algoritmo de Euclides.

Lea aquí para obtener más información: http://www.jimloy.com/number/euclids.htm

edición:

código (porque todo el mundo parece estar haciéndolo, esto no quiere utilizar la recursividad aunque)

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 para el manejo del numerador> denominador – Phrogz

5

Para reduce una fracción, divide el numerador y el denominador por el Factor común más grande. Phrogz y David ya han proporcionado el código fuente ...

Sin embargo, si está buscando bibliotecas de JavaScript para manejar fracciones, estas son algunas para elegir.

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

Aquí hay un ejemplo usando 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

Útil, gracias. He publicado una pregunta sobre las eficiencias relativas de estas bibliotecas aquí: http: // stackoverflow.com/questions/15840390/what-is-the-most-efficient-fraction-library-in-javascript? noredirect = 1 # comment22538987_15840390 – Omn

+1

@Omn ¿Ya describió el rendimiento usando jsperf.com? Si ve algún problema con Ratio.js cuando acaba de abrir un ticket, intentaré solucionarlo. https://github.com/LarryBattle/Ratio.js –

+0

No tengo experiencia creando y ejecutando benchmarks. Terminé yendo al código y mirando lo que parecía tener una mejor codificación, comentarios y funciones implementadas. Terminé yendo con Ratio.js pero no he tenido la oportunidad de trabajar en ese proyecto mucho desde entonces. Sin duda, te dejaré saber si encuentro algún problema y solo puedo contribuir con correcciones de errores si puedo ver el problema yo mismo. – Omn

1

sé que ya hay una respuesta, pero quiero compartir una biblioteca de JS que encontré cuando yo estaba buscando algo para números decimales convertir en fracciones y fracciones reduciendo.

La biblioteca llama al Fraction.js, lo cual fue realmente útil para mí y me ahorró mucho tiempo y trabajo. ¡Espero que pueda ser muy útil para otra persona!

0

Aquí hay una función recursiva usando ECMAScript 6 reduce. Funciona para la mayoría de las fracciones siempre que el resto no sea demasiado pequeño. 0 se ha redefinido para que funcione en arreglos como [1.2, 2.4, 12, 24]. Probé en Chrome e IE Edge por lo que puede comportarse de manera diferente en otros navegadores o actualizaciones. Por lo tanto, debería funcionar con una serie de flotadores.

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(); 

Buscar MDN reducir o más información here.

Cuestiones relacionadas