Is there a function like `range()`

but the steps are multiplicative?

Something like

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

Is there a function like `range()`

but the steps are multiplicative?

Something like

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

1 Like

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

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

1 Like

Thereās a PR to add it to base Add a lazy `LogRange` function by mcabbott Ā· Pull Request #39071 Ā· JuliaLang/julia Ā· GitHub. It tuns out that getting it perfect is surprisingly difficult.

2 Likes

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

5 Likes

FlexiMaps.jl provides logrange already, lazy/general/performant:

```
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?).

2 Likes