I am no expert, but how about something like this:

function histrange{T<:Number,N}(v::AbstractArray{T,N}, n::Integer)
    # Shortcut function.
    t(x) = oftype(T,x)
    
    if length(v) == 0
        return t(Range(0,1,1))
    end
    lo, hi = minimum(v), maximum(v)
    if hi == lo
        step = t(1)
    else
        bw = (hi - lo) / n
        e = t(10)^t(floor(log10(bw)))
        r = bw / e
        if r <= 2
            step = 2*e
        elseif r <= 5
            step = 5*e
        else
            step = 10*e
        end
    end
    start = step*t(ceil(lo/step)-1)
    Range(start,step,1+iceil((hi - start)/step))
end

Cheers,
Daniel.

On Thursday, 26 December 2013 07:47:09 UTC-5, Michael Fox wrote:
>
> It's kind of painful to see codes repeating themselves like this. Here's 
> one I just ran across in `statistics.jl`. Is there something about the type 
> or dispatch system that encourages or even requires such repetition? Can 
> you think of a better idea?
>
> ## nice-valued ranges for histograms
> function histrange{T<:FloatingPoint,N}(v::AbstractArray{T,N}, n::Integer)
>     if length(v) == 0
>         return Range(0.0,1.0,1)
>     end
>     lo, hi = minimum(v), maximum(v)
>     if hi == lo
>         step = 1.0
>     else
>         bw = (hi - lo) / n
>         e = 10.0^floor(log10(bw))
>         r = bw / e
>         if r <= 2
>             step = 2*e
>         elseif r <= 5
>             step = 5*e
>         else
>             step = 10*e
>         end
>     end
>     start = step*(ceil(lo/step)-1)
>     Range(start,step,1+iceil((hi - start)/step))
> end
>
> function histrange{T<:Integer,N}(v::AbstractArray{T,N}, n::Integer)
>     if length(v) == 0
>         return Range(0,1,1)
>     end
>     lo, hi = minimum(v), maximum(v)
>     if hi == lo
>         step = 1
>     else
>         bw = (hi - lo) / n
>         e = 10^max(0,ifloor(log10(bw)))
>         r = bw / e
>         if r <= 1
>             step = e
>         elseif r <= 2
>             step = 2*e
>         elseif r <= 5
>             step = 5*e
>         else
>             step = 10*e
>         end
>     end
>     start = step*(iceil(lo/step)-1)
>     Range(start,step,1+iceil((hi - start)/step))
> end
>
>

Reply via email to