Skip to content

Commit 55e2bd7

Browse files
authored
Fix rounding when converting Rational to BigFloat (#59063)
1 parent a2457e6 commit 55e2bd7

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
@@ -392,12 +392,18 @@ BigFloat(x::Union{Float16,Float32}, r::MPFRRoundingMode=rounding_raw(BigFloat);
392392
BigFloat(Float64(x), r; precision=precision)
393393

394394
function BigFloat(x::Rational, r::MPFRRoundingMode=rounding_raw(BigFloat); precision::Integer=_precision_with_base_2(BigFloat))
395+
r_den = _opposite_round(r)
395396
setprecision(BigFloat, precision) do
396397
setrounding_raw(BigFloat, r) do
397-
BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x))::BigFloat
398+
BigFloat(numerator(x))::BigFloat / BigFloat(denominator(x), r_den)::BigFloat
398399
end
399400
end
400401
end
402+
function _opposite_round(r::MPFRRoundingMode)
403+
r == MPFRRoundUp && return MPFRRoundDown
404+
r == MPFRRoundDown && return MPFRRoundUp
405+
return r
406+
end
401407

402408
function tryparse(::Type{BigFloat}, s::AbstractString; base::Integer=0, precision::Integer=_precision_with_base_2(BigFloat), rounding::MPFRRoundingMode=rounding_raw(BigFloat))
403409
!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)