Los Rational numbers son fracciones con un numerador entero dividido por un denominador entero.
Por ejemplo, podemos guardar 2//3 como una fracción exacta en lugar del valor aproximado de Float64 0.6666...
La ventaja es que (salvo en el caso extremo del desbordamiento de enteros) un número racional se mantiene exacto, lo que evita los errores de redondeo que a menudo son inevitables con los números de punto flotante.
Los números racionales son un tipo numérico bastante simple y están pensados para funcionar tal como esperarías. Como han sido un tipo estándar en Julia desde las primeras versiones, la mayoría de las funciones los aceptan como argumento igual que los enteros y los números de punto flotante.
Crearlos es tan simple como usar // entre dos enteros.
julia> 3//4
3//4
julia> a = 3; b = 4;
julia> a//b
3//4
Los factores comunes se eliminan automáticamente, lo que convierte la fracción a su «mínima expresión»: los enteros más pequeños que representan la fracción con exactitud y con un denominador no negativo.
julia> 5//15
1//3
julia> 5//-15
-1//3
Los arithmetic operators habituales + - * / ^ % funcionan con los racionales, esencialmente igual que con otros tipos numéricos.
Se pueden incluir enteros y otros Rationals en la expresión y el resultado será un Rational.
Si incluyes un float en la expresión, el resultado será un float, con la consiguiente (posible) pérdida de precisión.
Si quieres un float, solo usa la función float() para convertir un racional.
Es bastante normal usar números racionales para conservar la precisión a lo largo de un cálculo largo y luego convertir a número de punto flotante al final.
julia> 3//4 + 1//3 # addition
13//12
julia> 3//4 * 1//3 # multiplication
1//4
julia> 3//4 / 1//3 # division
9//4
julia> 3//4 ^ 2 # exponentiation
3//16
julia> 3//4 + 5 # rational and int => rational
23//4
julia> 3//4 + 5.3 # rational and float => float
6.05
julia> float(3//4) # casting
0.75
En Julia, los números racionales son solo números. Por lo general, el compilador convierte los tipos según sea necesario.
Sin embargo, ten en cuenta que las comparaciones funcionan para fracciones con una representación decimal finita:
julia> 3//4 == 0.75
true
julia> 3//4 < 0.74
false
Pero, en caso contrario, conviene convertir un Rational a Float para hacer comparaciones:
julia> 1//3 == 1/3
false
julia> float(1//3) == 1/3
true
Las funciones matemáticas aceptan racionales como argumento, pero pueden dar un resultado de punto flotante:
julia> sqrt(9//16)
0.75
Una organización de investigación se ha dado cuenta de que algunos de sus investigadores junior han estado usando métodos poco óptimos en sus análisis. Uno de estos métodos consiste en convertir de inmediato las probabilidades discretas en números de punto flotante (es decir, números reales) antes de hacer más cálculos.
Los investigadores senior prefieren usar números racionales en los cálculos, lo que puede dar mayor precisión, y quieren saber si las malas prácticas de los investigadores junior han afectado los resultados de los estudios.
Se hicieron dos tipos de estudios:
Los investigadores senior te piden que escribas funciones que les ayuden a determinar si hay errores de redondeo en los análisis al usar números de punto flotante, y que les proporciones un número racional preciso para el resultado en caso de que haya errores.
La función rationalize(successes, trials) recibe dos arrays, successes y trials.
Para un índice i, successes[i] corresponde al número de éxitos que ocurrieron en trials[i] ensayos.
La función devuelve un array de números racionales de los éxitos sobre el número de ensayos, en el mismo orden que los arrays originales.
julia> rationalize([1, 2, 3], [4, 5, 6])
3-element Vector{Rational{Int64}}:
1//4
2//5
1//2
De manera similar, la función probabilities(successes, trials) recibe dos arrays, successes y trials.
Devuelve un array de números de punto flotante de los éxitos sobre el número de ensayos, en el mismo orden que los arrays originales.
julia> probabilities([1, 2, 3], [4, 5, 6])
3-element Vector{Float64}:
0.25
0.4
0.5
La función checkmean(successes, trials) recibe los dos arrays, successes y trials.
Compara la media de las probabilidades reales con la media de las probabilidades racionales.
checkmean devuelve true
checkmean devuelve la probabilidad racional.julia> successes, trials = [9, 4, 7, 8, 6], [22, 22, 11, 17, 12];
julia> checkmean(successes, trials)
true
julia> successes, trials = [6, 5, 9, 8, 9], [21, 19, 13, 25, 22];
julia> checkmean(successes, trials)
1873629//4754750
La función checkprob(successes, trials) recibe los dos arrays, successes y trials.
Compara la probabilidad total de las probabilidades de punto flotante con la probabilidad total de las probabilidades racionales.
checkprob devuelve true
checkprob devuelve la probabilidad racional.julia> successes, trials = [2, 9, 4, 4, 5], [15, 11, 17, 19, 15];
julia> checkprob(successes, trials)
true
julia> successes, trials = [9, 8, 5, 4, 3], [22, 14, 19, 25, 18];
julia> checkprob(sucesses, trials)
12//7315
Regístrate en Exercism para aprender y dominar Julia con 35 conceptos128 ejercicios y mentoría humana real, todo gratis.