2011-01-13 13 views
5

En lugar de convertir un decimal arbitrario en una fracción exacta (algo así como 323527/4362363), trato de convertirlo en algo común fácilmente discernible (en términos humanos) legibilidad) cantidades como 1/2, 1/4, 1/8, etc.Algoritmo optimizado para convertir un decimal en una fracción "bonita"

Además de usar una serie de comparaciones if-then, menos que/igual a etc., ¿hay técnicas más optimizadas para hacer esto?

Editar: En mi caso particular, las estimaciones son aceptables. La idea es que 0,251243 ~ 0,25 = 1/4 - en mi caso de uso, eso es "lo suficientemente bueno", siendo este último más preferible para la legibilidad humana en términos de un indicador rápido (no se utiliza para el cálculo, solo se usa como números de visualización).

+0

Su pregunta es vaga. ¿Cómo defines la legibilidad humana? Y más importante aún, ¿qué pasa si no hay una forma equivalente legible para humanos? ¿Permites aproximaciones? Personalmente, no veo ninguna manera fácil de escribir su ejemplo, 323526/4362363, en forma legible para humanos sin recurrir a la aproximación. –

+0

Aproximaciones son aceptables - La precisión decimal de 4 dígitos es más que suficiente – ina

+0

Sin embargo, hay algo más "legible por humanos", que simplemente la longitud de cualquiera de los números. En general, las fracciones de la forma "1/x" son * fáciles * pero "4/85" es simplemente extraño y se expresaría mejor como "1/41". Por supuesto, la familia "1/x" solo funciona bien para números menores a 0.5, y aproximarse a 0.4 significa una gran pérdida ... ¿tal vez una representación porcentual sería adecuada? –

Respuesta

3

Puede usar el algoritmo euclidiano para obtener el Divisor común más grande entre el enumerador y el denominador y dividirlo por él.

+0

También recomendaría limitar su denominador a algo razonable para evitar casos como 107842/1454121 (que es su ejemplo, reducido). – coreyward

+0

mea culpa - typo'd esa fracción inicial ... significaba un 7 en lugar de un 6 ;-) – ina

+0

¿Por qué la gente está votando esto? Esto no responde la pregunta en absoluto. Está preguntando acerca de la aproximación de decimales a fracciones simples, no sobre la reducción de fracciones. –

7

Buscar "aproximación continua de fracciones". Wikipedia tiene una introducción básica en su artículo de "fracción continua", pero hay algoritmos optimizados que generan el valor aproximado al generar la fracción.

A continuación, elija alguna heurística de detención, una combinación del tamaño del denominador y la cercanía de la aproximación, para cuando esté "lo suficientemente cerca".

0

A continuación, supongo que nuestros decimales están entre 0 y 1. Debería ser sencillo adaptar esto a números más grandes y números negativos.

Probablemente lo más fácil sería elegir el mayor denominador que encontraría aceptable y luego crear una lista de fracciones entre 0 y 1 que tengan los denominadores inferiores o iguales a ellas. Asegúrese de evitar cualquier fracción que pueda simplificarse. Obviamente, una vez que has enumerado 1/2, no necesitas 2/4. Puede evitar fracciones que pueden simplificarse verificando que el GCD del numerador y el denominador es 1 que demanda el algoritmo de Euclides. Una vez que tengas tu lista. Evalúe estos como números de coma flotante (probablemente se duplique, pero el tipo de datos obviamente depende de su elección de lenguaje de programación). Luego, insértelos en un árbol de búsqueda binaria equilibrado que almacene tanto la fracción original como la evaluación en coma flotante de la fracción. Solo debe hacer esto una vez para configurarlo inicialmente, por lo que el tiempo n * log (n) (donde n es el número de fracciones) no es mucho.

Luego, cada vez que obtenga un número, simplemente busque en el árbol para encontrar el número más cercano que se encuentra en el árbol de búsqueda. Tenga en cuenta que esto es un poco más complicado que buscar una coincidencia exacta porque el nodo que está buscando puede no ser un nodo hoja. Entonces, mientras recorre el árbol, mantenga un registro del nodo valorado más cercano que haya visitado. Una vez que llegue a un nodo hoja y compare ese nodo con el nodo valorado más cercano que haya visitado, habrá terminado. Cualquiera que sea el más cercano, su fracción es su fracción.

0

Aquí es una sugerencia: Asumiendo que su fracción de partida es p/q

  1. Calcular r = p/q como un valor racional (coma flotante) (por ejemplo,r = flotador (p)/flotador (q))

  2. Calcular el redondeado decimal x = int (10.000 * r)

  3. Calcular GCD (denominador máximo común) de x y 10000: s = GCD (x, 10000)

  4. representar el resultado como m/n, donde m = x/s y n =/s y (su ejemplo calcula a 371/5000)

Normalmente, todos los denominadores de 1000 son bastante legibles por humanos

Esto puede no proporcionar el mejor resultado cuando el valor está más cerca de casos más simples como 1/3. Sin embargo, personalmente encuentro que 379/1000 es mucho más legible para humanos que 47/62 (que es la representación fraccional más corta). Sin embargo, puede agregar algunas excepciones para afinar ese proceso (por ejemplo, calcular el p/GCD (p, q), q/GCD (p, q) y aceptarlo si uno de esos valores son de un solo dígito antes de continuar con este método)

0

solución bastante tonto, sólo por fracción "vista previa":

 
factor = 1/decimal 
result = 1/Round(factor) 
mult = 1 

while (result = 1) { 
    mult = mult * 10 
    result = (1 * mult)/(Round(mult * factor)) 
} 

result = simplify_with_GCD(result) 

buena suerte!

Cuestiones relacionadas