- Sponsor
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Description
Conversion of irrationals to Float64
with a specified rounding mode is currently done by evaluating the irrational with BigFloat
at 256 bits of precision and then rounding the result. This can lead to issues if 256 bits is not enough to correctly round the result. There are not examples like this in Base, but one could for example define the (fairly useless) irrational number
julia> Base.@irrational almost_one (1 - big(π)^-300)
julia> almost_one
almost_one = 1.0...
julia> Float64(almost_one, RoundDown)
1.0
julia> almost_one < 1
false
julia> BigFloat(almost_one)
1.0
julia> setprecision(() -> BigFloat(almost_one), 512)
0.999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999992837905
If one takes the exponent to be for example -100
then it works correctly, since 256 bits is then enough to get correct rounding.
This is clearly an extreme example and I don't think this would be a practical problem for anyone. But it does mean one has to be careful if the goal is to prove properties of an irrational, which would be relevant in for example IntervalArithmetic.jl.
Activity
aravindh-krishnamoorthy commentedon Jan 17, 2024
I must preface this by saying that I'm working with Julia only since a few months. Indeed setting the precision to solves one of the problems. By using:
we get:
However, as we note,
almost_one < 1
is still false.But, quirkily, even with
setprecision(BigFloat, 256)
Joel-Dahne commentedon Jan 17, 2024
Indeed increasing the precision fixes this specific case, but one could of course find other counter examples then! One could solve this by iteratively computing at higher precision, until one gets a result that is strictly between two
Float64
values.Thanks to your comment I also noticed that I gave the inequality in the wrong direction in my original comment.
almost_one < 1
fails due to the conversion, not the rounding. As you mentionalmost_one < 1.0
works correctly. It is the below code that fails due to the rounding.aravindh-krishnamoorthy commentedon Jan 17, 2024
Thank you; indeed for any
exponent
insetprecision(BigFloat, exponent)
, we can always find a number that will failalmost_one > 1.0
with the current method of handling irrational numbers. Perhaps the right way of handling this is to change the current method of comparison with floats?On the other hand, I also feel that consistency is required between the results of
almost_one < 1
andalmost_one < 1.0
. In both cases, one of the operands is irrational (a "higher" class), so whether1
is interpreted as anInt64
orFloat64
must not matter for the final result?