# Is there a log scale range function?

**URL:** <https://discourse.julialang.org/t/is-there-a-log-scale-range-function/90354>\
**Category:** New to Julia\
**Tags:** question\
**Created:** [November 16, 2022, 3:05pm UTC](https://discourse.julialang.org/t/is-there-a-log-scale-range-function/90354 "2022-11-16T15:05:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![AwesomeQuest](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/awesomequest/32/38910_2.png) [@AwesomeQuest](https://discourse.julialang.org/u/AwesomeQuest)\
**Post date:** [November 16, 2022, 3:05pm UTC](https://discourse.julialang.org/t/is-there-a-log-scale-range-function/90354/1 "2022-11-16T15:05:51Z")

</div>

Is there a function like `range()` but the steps are multiplicative?  
Something like

```julia
logrange(start,stepmul,length) = cumprod([start,(ones(length)*stepmul)...])

```

---

<div class="post-metadata">

**Author:** ![bert](https://avatars.discourse-cdn.com/v4/letter/b/9e8a1a/32.png) [@bert](https://discourse.julialang.org/u/bert)\
**Post date:** [November 16, 2022, 3:14pm UTC](https://discourse.julialang.org/t/is-there-a-log-scale-range-function/90354/2 "2022-11-16T15:14:21Z")

</div>

You can use broadcasting to apply a log transform to a range:

```nohighlight
julia> logrange(start,stepmul,length) = start .* stepmul .^ (0:(length-1))
logrange (generic function with 1 method)

julia> logrange(3, 4, 5)
5-element Vector{Int64}:
   3
  12
  48
 192
 768

```

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [November 16, 2022, 3:23pm UTC](https://discourse.julialang.org/t/is-there-a-log-scale-range-function/90354/3 "2022-11-16T15:23:02Z")

</div>

There’s a PR to add it to base [Add a lazy `LogRange` function by mcabbott · Pull Request #39071 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/39071). It tuns out that getting it perfect is surprisingly difficult.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [November 16, 2022, 3:43pm UTC](https://discourse.julialang.org/t/is-there-a-log-scale-range-function/90354/4 "2022-11-16T15:43:29Z")

</div>

The tricky thing about a function which takes the ratio (`stepmul` above) is that it will tend to create an expectation that this be interpreted exactly.

Linear ranges like `0:0.1:1` do this, by some serious black magic. It knows you mean `1//10` even though that isn’t precisely represented by any Float64. Doing `cumsum(fill(0.1, 10))` will miss the “obvious” endpoint of `1.0`.

Similar things go wrong for ratio `0.1`:

```julia
julia> logrange1(100, 0.1, 5) # from 1st message, with stepmul
6-element Vector{Float64}:
 100.0
  10.0
   1.0
   0.1
   0.010000000000000002
   0.0010000000000000002

julia> logrange2(100, 0.1, 5) # from 2nd message above
5-element Vector{Float64}:
 100.0
  10.0
   1.0000000000000002
   0.10000000000000002
   0.010000000000000002

julia> logrange(100, ratio=0.1, length=5) # lazy PowerRange, somewhere in PR
5-element PowerRange{Float64}:
 100.0
  10.0
   1.0000000000000002
   0.10000000000000002
   0.010000000000000002

```

The linked PR avoids this by taking the first & last values. Then there’s no chance that it doesn’t stop where you want, it can simply guarantee to hit `0.01` exactly, without enquiring further. (It tries hard to be accurate in between, but isn’t perfect.)

```julia
julia> Base.logrange(100, 0.01, length=5)
5-element LogRange{Float64, Base.TwicePrecision{Float64}}:
 100.0, 10.0, 1.0, 0.1, 0.01

julia> collect(ans)
5-element Vector{Float64}:
 100.0
  10.0
   1.0
   0.1
   0.01

```

And apart from such details, in real use I think it’s common to do that, and then decide you want more / less points (on your plot), or a wider / narrower range (to exclude the bad ones). With the ratio specified, you have to experiment a bit. Specifying the ends and length seems to me more often useful.

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [November 17, 2022, 12:09am UTC](https://discourse.julialang.org/t/is-there-a-log-scale-range-function/90354/5 "2022-11-17T00:09:31Z")

</div>

[FlexiMaps.jl](https://gitlab.com/aplavin/FlexiMaps.jl) provides logrange already, lazy/general/performant:

```julia
julia> using FlexiMaps

julia> maprange(log, 0.1, 100, length=4) # ≈ [0.1, 1, 10, 100]

```

Specifying the step ratio directly would also be useful sometimes, but not supported (yet?).
