Skip to content

Commit 8e5455f

Browse files
OlivierHntaviatesk
authored andcommitted
Fix rounding when converting Rational to BigFloat (#59063)
1 parent 48d5276 commit 8e5455f

File tree

2 files changed

+10
-1
lines changed

2 files changed

+10
-1
lines changed

base/mpfr.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,12 +391,18 @@ BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=rounding_raw(BigFloat);
391391
BigFloat(Float64(x), r; precision=precision)
392392

393393
function BigFloat(x::Rational, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat))
394+
r_den = _opposite_round(r)
394395
setprecision(BigFloat, precision) do
395396
setrounding_raw(BigFloat, r) do
396-
BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x))::BigFloat
397+
BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x), r_den)::BigFloat
397398
end
398399
end
399400
end
401+
function _opposite_round(r::MPFRRoundingMode)
402+
r == MPFRRoundUp && return MPFRRoundDown
403+
r == MPFRRoundDown && return MPFRRoundUp
404+
return r
405+
end
400406

401407
function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=_precision_with_base_2(BigFloat), rounding::MPFRRoundingMode=rounding_raw(BigFloat))
402408
!isempty(s) && isspace(s[end]) && return tryparse(BigFloat, rstrip(s), base = base)

test/mpfr.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ import Base.MPFR
3535

3636
@test typeof(BigFloat(1//1)) == BigFloat
3737
@test typeof(BigFloat(one(Rational{BigInt}))) == BigFloat
38+
rat = 1 // (big(2)^300 + 1)
39+
@test BigFloat(rat, RoundDown) < rat < BigFloat(rat, RoundUp)
40+
@test BigFloat(-rat, RoundUp) < -rat < BigFloat(-rat, RoundDown)
3841

3942
# BigFloat constructor respects global precision when not specified
4043
let prec = precision(BigFloat) < 16 ? 256 : precision(BigFloat) ÷ 2

0 commit comments

Comments
 (0)