Skip to content

Inaccuracies for LinRange #37276

@ffevotte

Description

@ffevotte

This is a follow-up to discourse thread "Bug in floating-point range?".

The most minimal example I could come up with to evidence the issue is the following one:

function test_range(T)
    @show r = range(T(0), stop=T(1), length=11)
    @show val = r[2]
    ref = 1//10
    err = (Rational{BigInt}(val) - ref) / ref  |> abs |> Float64
    @show err
end

Indexing into a LinRange{BigFloat} gives very accurate results, with errors in the order of ulp(BigFloat):

julia> test_range(BigFloat);
r = range(T(0), stop = T(1), length = 11) = range(0.0, stop=1.0, length=11)
val = r[2] = 0.1000000000000000000000000000000000000000000000000000000000000000000000000000002
err = 2.1590421387736112e-78

However, the same calculation performed on a LinRange{Complex{BigFloat}} is much less accurate, with errors in the same order of magnitude as if 64-bit floats had been used:

julia> test_range(Complex{BigFloat});
r = range(T(0), stop = T(1), length = 11) = range(0.0 + 0.0im, stop=1.0 + 0.0im, length=11)
val = r[2] = 0.1000000000000000055511151231257827021181583404541015625 + 0.0im
err = 5.551115123125783e-17

julia> test_range(Complex{Float64});
r = range(T(0), stop = T(1), length = 11) = range(0.0 + 0.0im, stop=1.0 + 0.0im, length=11)
val = r[2] = 0.1 + 0.0im
err = 5.551115123125783e-17

As mentioned in the discourse thread above, I think I have identified Base.lerpi as the origin of the issue:

julia> Base.lerpi(1, 10, big"0.", big"1.")
0.1000000000000000000000000000000000000000000000000000000000000000000000000000002

julia> Base.lerpi(1, 10, Complex(big"0."), Complex(big"1.")) |> real
0.1000000000000000055511151231257827021181583404541015625

and I think I have a fix for this. I'll try and propose a PR as soon as I can.

Metadata

Metadata

Assignees

Labels

rangesEverything AbstractRange

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions