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
>>>
>>>

Reply via email to