Skip to content

Commit fbca2e5

Browse files
simonbyrnetkf
authored andcommitted
Fix RoundNearestTiesAway (JuliaLang#29700)
Fixes JuliaLang#29698.
1 parent 13b9c99 commit fbca2e5

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

base/floatfuncs.jl

+2-3
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,8 @@ function round(x::AbstractFloat, ::RoundingMode{:NearestTiesAway})
214214
ifelse(x==y,y,trunc(2*x-y))
215215
end
216216
# Java-style round
217-
function round(x::AbstractFloat, ::RoundingMode{:NearestTiesUp})
218-
y = floor(x)
219-
ifelse(x==y,y,copysign(floor(2*x-y),x))
217+
function round(x::T, ::RoundingMode{:NearestTiesUp}) where {T <: AbstractFloat}
218+
copysign(floor((x + (T(0.25) - eps(T(0.5)))) + (T(0.25) + eps(T(0.5)))), x)
220219
end
221220

222221
# isapprox: approximate equality of numbers

test/rounding.jl

+41
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,47 @@ end
9191
@test_throws DivideError round(Int64,badness,RoundNearestTiesUp)
9292
end
9393

94+
@testset "rounding properties" for Tf in [Float16,Float32,Float64]
95+
# these should hold for all u, but we just test the smallest and largest
96+
# of each binade
97+
98+
for i in exponent(floatmin(Tf)):exponent(floatmax(Tf))
99+
for u in [ldexp(Tf(1.0), i), -ldexp(Tf(1.0), i),
100+
ldexp(prevfloat(Tf(2.0)), i), -ldexp(prevfloat(Tf(2.0)), i)]
101+
102+
r = round(u, RoundNearest)
103+
if isfinite(u)
104+
@test isfinite(r)
105+
@test isinteger(r)
106+
@test abs(r-u) < 0.5 || abs(r-u) == 0.5 && isinteger(r/2)
107+
@test signbit(u) == signbit(r)
108+
else
109+
@test u === r
110+
end
111+
112+
r = round(u, RoundNearestTiesAway)
113+
if isfinite(u)
114+
@test isfinite(r)
115+
@test isinteger(r)
116+
@test abs(r-u) < 0.5 || (r-u) == copysign(0.5,u)
117+
@test signbit(u) == signbit(r)
118+
else
119+
@test u === r
120+
end
121+
122+
r = round(u, RoundNearestTiesUp)
123+
if isfinite(u)
124+
@test isfinite(r)
125+
@test isinteger(r)
126+
@test -0.5 < r-u <= 0.5
127+
@test signbit(u) == signbit(r)
128+
else
129+
@test u === r
130+
end
131+
end
132+
end
133+
end
134+
94135
@testset "rounding difficult values" begin
95136
for x = 2^53-10:2^53+10
96137
y = Float64(x)

0 commit comments

Comments
 (0)