Unfortunately, it is not always possible to construct a range such that the
exact value of the endpoints is retained. Matlab cheats here, and changes
the step size to ensure that the endpoints are retained. A Julian range,
however, must always have one unique step. For more information, see the
PR where linrange was
introduced: https://github.com/JuliaLang/julia/pull/6627. I agree that it
might make sense to futz with the implementation a bit to ensure that the
endpoint is always <= the requested one (see my comment).
In Julia:
julia> linrange(.3,.9,3)
0.3:0.30000000000000004:0.9000000000000001
julia> .3 + .3*2
0.8999999999999999
julia> .3 + nextfloat(.3)*2
0.9000000000000001
As compared to Matlab:
>> format longE
>> s = linspace(.3,.9,3)
s =
3.000000000000000e-01 6.000000000000001e-01
9.000000000000000e-01
>> diff(s)
ans =
3.000000000000001e-01 2.999999999999999e-01
On Wednesday, July 2, 2014 9:11:18 AM UTC-4, Peter Simon wrote:
>
> Thanks. I had mistakenly thought that linrange would retain the exact
> value of its end points, as does linspace.
>
> My actual application is to reproduce the functionality of Matlab's
> optional histc output:
>
> [n,bin] = histc(x, edges)
>
>
> Here, (using Matlab notation), bin is an integer-valued vector of the same
> length as x such that bin(i) indicates which "bin" of edges is occupied by
> x(i). My Julian attempt at reproducing this function used a range named
> edges:
>
> edges = linrange(minimum(x), maximum(x), 20)
> bin = [find(edges[1:end-1] .<= t .<= edges[2:end])[1] for t in x]
>
>
>
> and it failed due to the issue demonstrated in my first post. I think
> that I could use linspace instead of linrange, but for other reasons a
> range is preferable in this application. Do we already have this binning
> functionality in some other built-in function? I checked Julia's hist(),
> but it provides only the first output of Matlab's bin.
>
> Thanks,
> --Peter
>
> On Tuesday, July 1, 2014 11:59:44 PM UTC-7, Ivar Nesje wrote:
>>
>> It is not a shocker to me. The problem is that Floating point numbers
>> represent binary fractions, and there is no way for linrange() to actually
>> get equidistant values you are looking for. It has to do approximations,
>> and thus it will sometimes miss closest possible value. That means equality
>> checks on floating point numbers should be used with extreme care.
>>
>> Our implementation reuses the old step size when indexing a FloatRange
>> with a range, but we could probably do better if we tried to keep the last
>> point equal.
>>
>> I reopened https://github.com/JuliaLang/julia/issues/7420 to keep track
>> of this issue.
>>
>> Ivar
>>
>> kl. 07:07:25 UTC+2 onsdag 2. juli 2014 skrev Peter Simon følgende:
>>>
>>> The final result below seems really strange to me. A bug?
>>>
>>> julia> x = linrange(1,10,20)
>>> 1.0:0.47368421052631576:10.0
>>>
>>>
>>> julia> 10 .<= x # Gives expected result
>>> 20-element BitArray{1}:
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> true
>>>
>>> julia> 10 .<= x[end] # Gives expected result
>>> true
>>>
>>> julia> 10 .<= x[2:end] # The last entry in this result is a shocker to
>>> me!
>>> 19-element BitArray{1}:
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>> false
>>>
>>>
>>>
>>> Here is the version info:
>>>
>>>
>>> julia> versioninfo()
>>> Julia Version 0.3.0-prerelease+3987
>>> Commit 7dd97fa (2014-06-30 23:12 UTC)
>>> Platform Info:
>>> System: Windows (x86_64-w64-mingw32)
>>> CPU: Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz
>>> WORD_SIZE: 64
>>> BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY)
>>> LAPACK: libopenblas
>>> LIBM: libopenlibm
>>>
>>>