I’m just getting started with Julia and I ran across something that confused me in this section of the docs; Promotion. It shows the following example:
I was surprised that the Rational was promoted to a Float. It seems like you can lose accuracy with that conversion. I tried the following and I think this confirms my suspicion:
julia> a,b = promote(0.25, 1//10)
(0.25, 0.1)
julia> @printf("%.55f\n%.55f", a, b)
0.2500000000000000000000000000000000000000000000000000000
0.1000000000000000055511151231257827021181583404541015625
julia> convert(Rational, b)
3602879701896397//36028797018963968
The Float is not exactly 1/10 and the value doesn’t round-trip back to 1/10.
I’m wondering, is there an explanation or discussion about this that I can read? If I wanted to reverse this behavior (convert the Float to a Rational in this case), is that something I can override?
Thanks @Tamas_Papp! As I mentioned, I’m just getting started, so my concern may be unfounded. The short version is that I’m porting some code over to Julia to help analyze some math issues I’m seeing. I’d like to be able to run the code using different types of Reals: Float64, BigFloat, and Rational{BigInt}. Most likely, I just need to be careful how I handle any constants in the code outside of zeros and ones. I believe operators are restricted to +, -, *, and /.
To be precise, a Rational and Float64 promote to Float64. (A Rational and an Int promote to a Rational, for example.) The basic principle is that floating-point values are typically inexact approximations for some other real number, so if you are combining them with a rational value you usually expect an inexact result anyway. In that case, converting the rational to the closest floating-point value is not typically a problem.
Keeping things as Rational values during computations, on the other hand, is unusual for the reasons @Tamas_Papp mentioned.
If you want exact rational constants like 1.25 in your code that are automatically converted to the best precision when combined with other values, it is better to represent them as Rational values like 5//4.