JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.54k stars 5.47k forks source link

`a==b` but `collect(a)!=collect(b)` for `a` and `b` being `StepRangeLen{Float64,...}` #50039

Open mauro3 opened 1 year ago

mauro3 commented 1 year ago

I encountered this

# neither range goes till their endpoint
a = 0:1/24:365 - 1/48 - 0.001
b = 0:1/24:365 - 1/48
typeof(a) # StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}

a==b  # true
collect(a)==collect(b) # false!!!
a===b  # false
step(a) == step(b)  # true

first(a) == first(b) # true
last(a) == last(b) # true
a[6] == b[6]  # false!!!
sum(a.!=b)/length(a) # about ~1/3 of values are not equal!!!

The things which surprised me:

I understand that range maths is super complicated. So this may well be expected, please close if that is the case.

oscardssmith commented 1 year ago

I had convinced myself this was impossible :(.

nsajko commented 1 year ago

Perhaps this has something to do with the faulty normalization

julia> a = 0:1/24:365 - 1/48 - 0.001
0.0:0.041666666666666664:364.9583333333333

julia> b = 0:1/24:365 - 1/48
0.0:0.041666666666666664:364.9583333333333

julia> a.step
Base.TwicePrecision{Float64}(0.041666666666666664, 0.0)

julia> x = b.step
Base.TwicePrecision{Float64}(0.041666666666515084, 1.5158245029548803e-13)

julia> x.lo + x.hi
0.041666666666666664
LilithHafner commented 1 year ago

Well found! This bug has been around since at least 1.0.