# How to create a \`range\` centered around zero?

**URL:** https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344
**Category:** General Usage
**Tags:** question
**Created:** [April 15, 2021, 2:00pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344 "2021-04-15T14:00:07Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 2:00pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/1 "2021-04-15T14:00:07Z")

</div>

is there a way to make a `range(-max, max, step=n)` that is guaranteed to go through zero?, i.e. I want it to be symmetrical/centered around zero

---

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 2:01pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/2 "2021-04-15T14:01:25Z")

</div>

From @briochemc on Slack  
make a struct

```julia
struct SymmetricRange{A,B}
    max::A
    step::B
end

```

and define everything you need on it? E.g.,

```julia
Base.collect(r::SymmetricRange) = [reverse(collect(range(0, -r.max, step=-r.step)))[1:end-1]; collect(range(0, r.max, step=r.step))]
gives
julia> collect(SymmetricRange(1, 0.32))
7-element Vector{Float64}:
 -0.96
 -0.64
 -0.32
  0.0
  0.32
  0.64
  0.96

```

---

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 2:03pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/3 "2021-04-15T14:03:08Z")

</div>

From @Sukera:

also `iterate` and you should be set  
won’t even need to roll your own `collect` then and it’ll work in loops just as well

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [April 15, 2021, 2:43pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/4 "2021-04-15T14:43:47Z")

</div>

I would not recommend the solutions already given but instead just create a function that returns a carefully assembled range `-max:step:max` that has such guarantee (i.e., by slightly changing both `-max` and `max`). Of course, if you need to deal with floating point numbers this may be a problem.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [April 15, 2021, 2:49pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/5 "2021-04-15T14:49:25Z")

</div>

Why not `range(-x, x, length=some_odd_number)`? A few quick loops shows it seems to work pretty consistently, but floating point is wild and I don’t trust it fully. How important is the exact zero? How important are the endpoints? How important is the step size? You’re not going to be able to hit all of those requirements exactly no matter what you do.

---

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 2:53pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/6 "2021-04-15T14:53:24Z")

</div>

@mbauman because `step` is a `Real` number. Maybe I should have written that `step=dx` instead of `n`

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [April 15, 2021, 2:55pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/7 "2021-04-15T14:55:48Z")

</div>

Yeah, so recompute it to the equivalent length? Again, this gets to your requirements: it’s impossible to answer this question without knowing how exactly you want to hit endpoints, zero, and the step itself.

---

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 2:58pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/8 "2021-04-15T14:58:00Z")

</div>

In MATLAB people do this:

```julia
x = [-1*fliplr(dx:dx:max), 0:dx:max];

```

Which I could do in Julia.e.g.  
`mysymrange(max, dx) = vcat(range(0,-max,step=-dx) |> reverse, range(0, max, step=dx))`

… and get over with, but I would like to have a `range` 🙂

julia\> mysymrange(1.1, 0.2)  
12-element Vector{Float64}:  
-1.0  
-0.8  
-0.6  
-0.4  
-0.2  
0.0  
0.0  
0.2  
0.4  
0.6  
0.8  
1.0

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [April 15, 2021, 3:03pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/9 "2021-04-15T15:03:59Z")

</div>

I think if you want (i) an exact zero (ii) working with floating points and (iii) not allocating more memory than necessary then the solution with a custom `struct` implementing `iterate` is, in fact, the best one. Maybe inherit `AbstractRange` too.

---

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 3:05pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/10 "2021-04-15T15:05:05Z")

</div>

@Henrique_Becker I thought so 😃

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [April 15, 2021, 3:08pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/11 "2021-04-15T15:08:57Z")

</div>

You may be interested in using `StepRangeLen` directly:

```julia
help?> StepRangeLen
search: StepRangeLen StepRange

  StepRangeLen{T,R,S}(ref::R, step::S, len, [offset=1]) where {T,R,S}
  StepRangeLen( ref::R, step::S, len, [offset=1]) where { R,S}

  A range r where r[i] produces values of type T (in the second form, T is deduced automatically), parameterized by a
  reference value, a step, and the length. By default ref is the starting value r[1], but alternatively you can supply
  it as the value of r[offset] for some other index 1 <= offset <= len. In conjunction with TwicePrecision this can be
  used to implement ranges that are free of roundoff error.

julia> StepRangeLen(0, 0.35353, 11, 6)
-1.7676500000000002:0.35353:1.7676500000000002

julia> collect(StepRangeLen(0, 0.35353, 11, 6))
11-element Vector{Float64}:
 -1.7676500000000002
 -1.41412
 -1.06059
 -0.70706
 -0.35353
  0.0
  0.35353
  0.70706
  1.06059
  1.41412
  1.7676500000000002

```

Set the reference point to `0` and set the offset to be the middle of your range.

---

<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: [April 15, 2021, 3:11pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/12 "2021-04-15T15:11:59Z")

</div>

I think it ought to be possible to re-use `StepRangeLen` for this, with a new constructor. Here’s a naiive one which takes a given step, and (if I understood it right) it measures distances from zero here (not by adding to one end) so should hit that exactly:

```julia
julia> function zed(step, length)
         isodd(length) || error()
         StepRangeLen(zero(step), step, length, 1 + length÷2)
       end;

julia> zed(1/3, 7) |> collect
7-element Vector{Float64}:
 -1.0
 -0.6666666666666666
 -0.3333333333333333
  0.0
  0.3333333333333333
  0.6666666666666666
  1.0

```

A constructor to always hit a given `max` exactly would probably need similar TwicePrecision tricks to what Base uses.

(Edit: scooped by @mkitti!)

Edit: It looks like `range(-m, m; length)` often produces exactly this, with `ref == 0.0` and `offset == (length+1)/2`:

```julia
julia> m = nextfloat(123e123); 

julia> range(-m, m, length=10^6 + 1) |> dump
StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}
  ref: Base.TwicePrecision{Float64}
    hi: Float64 0.0
    lo: Float64 0.0
  step: Base.TwicePrecision{Float64}
    hi: Float64 2.459999999995291e119
    lo: Float64 4.7094854703847126e107
  len: Int64 1000001
  offset: Int64 500001

```

But not always, here’s an example:

```julia
julia> m = 1.2057884f13; n = 105; r = range(-m, m, length=n)
-1.2057884f13:2.3188238f11:1.2057884f13

julia> r.ref, r.offset
(1.0, 53)

julia> r[[52, 53, 54]]
3-element Vector{Float32}:
 -2.3188238f11
  1.0
  2.3188238f11

```

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [April 15, 2021, 3:12pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/13 "2021-04-15T15:12:52Z")

</div>

Another way, edited to be in line with requested behavior:

```julia
function range0(x, dx)
  n = Int(floor(x/dx))
  (-n:n)*dx
end

x = 1.1
dx = 0.25
julia> range0(x,dx)
-1.0:0.25:1.0

```

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [April 15, 2021, 3:12pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/14 "2021-04-15T15:12:57Z")

</div>

When I saw [mcabbott](https://discourse.julialang.org/u/mcabbott) starting to type, I knew I better hurry up and push post. 🙂

---

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 3:22pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/15 "2021-04-15T15:22:22Z")

</div>

Hmmm… the problem with `StepRangeLen` is that I have to specify the `length` which I guess you thought it could me `max` but it is not an integer

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [April 15, 2021, 3:25pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/16 "2021-04-15T15:25:47Z")

</div>

Just divide the `max` by the `step` and floor it, double it, and add one. Again, though, you need to carefully consider your requirements that I keep trying to get you to define 🙂

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [April 15, 2021, 3:29pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/17 "2021-04-15T15:29:09Z")

</div>

> [@mbauman](#):
>
> `ax` by the `step` and floor it, double it,

😬

I was just asking what is the problem with this:

```julia
julia> function srange(dx,xmax)
         n = floor(xmax/dx)
         smin = -n*dx
         smax = n*dx
         smin:dx:smax
       end
srange (generic function with 1 method)

julia> collect(srange(0.8,5.6))
13-element Vector{Float64}:
 -4.800000000000001
 -4.000000000000001
 -3.2000000000000006
 -2.4000000000000004
 -1.6000000000000005
 -0.8000000000000007
  0.0
  0.7999999999999998
  1.5999999999999996
  2.3999999999999995
  3.1999999999999993
  4.0
  4.800000000000001

```

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [April 15, 2021, 4:15pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/18 "2021-04-15T16:15:06Z")

</div>

The problem is that we need obey this equation:

```julia
max = step * length

```

and have `isinteger(length) == true`.

We could do something like this, but as you can see it gets really messy very quickly.

```julia
julia> function zed_step_max(step::T, max::T) where T
           length = max / step
           isinteger(length) || error("step does not evenly divide max")
           length = Integer(length)*2 + 1
           StepRangeLen{T}(zero(step), step, length, 1 + length÷2)
       end
zed_step_max (generic function with 2 methods)

julia> zed_step_max(0.0001, 0.3535)
ERROR: step does not evenly divide max
Stacktrace:
 [1] error(s::String)
   @ Base .\error.jl:33
 [2] zed_step_max(step::Float64, max::Float64)
   @ Main .\REPL[156]:3
 [3] top-level scope
   @ REPL[157]:1

julia> zed_step_max(0.0001, 0.3536)
-0.3536:0.0001:0.3536

julia> 0.3535 / 0.0001
3534.9999999999995

julia> 0.3536 / 0.0001
3536.0

```

The problem is [IEEE 754 floating point](https://en.wikipedia.org/wiki/IEEE_754). Clearly though “0.3535” should be divisble by “0.001”, so how do we fix this to make it Just Work™?

To just get the result, we can try to bypass floating point arithmetic by using `rationalize`:

```julia
julia> function zed_step_max_rationalize(step::T, max::T) where T
           step, max = rationalize.( (step,max) )
           length = max / step
           isinteger(length) || error("step does not evenly divide max")
           length = Integer(length)*2 + 1
           StepRangeLen{T}(zero(step), step, length, 1 + length÷2)
       end
zed_step_max_rationalize (generic function with 1 method)

julia> zed_step_max_rationalize( 0.0001, 0.3535 )
-0.3535:0.0001:0.3535

julia> zed_step_max_rationalize( 0.0001, 0.3536 )
-0.3536:0.0001:0.3536

julia> r = zed_step_max_rationalize(0.0001, 0.3535)
       mid = length(r)÷2 + 1
       @info "" r[1] r[2] r[mid-1] r[mid] r[mid+1] r[end-1] r[end]
┌ Info:
│ r[1] = -0.3535
│ r[2] = -0.3534
│ r[mid - 1] = -0.0001
│ r[mid] = 0.0
│ r[mid + 1] = 0.0001
│ r[end - 1] = 0.3534
└ r[end] = 0.3535

julia> r = zed_step_max_rationalize(0.0001, 0.3536)
       mid = length(r)÷2 + 1
       @info "" r[1] r[2] r[mid-1] r[mid] r[mid+1] r[end-1] r[end]
┌ Info:
│ r[1] = -0.3536
│ r[2] = -0.3535
│ r[mid - 1] = -0.0001
│ r[mid] = 0.0
│ r[mid + 1] = 0.0001
│ r[end - 1] = 0.3535
└ r[end] = 0.3536

```

---

<div class="post-metadata">

### Author: ![Jorge\_Vieyra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jorge_vieyra/32/6527_2.png) [@Jorge\_Vieyra](https://discourse.julialang.org/u/Jorge_Vieyra)
#### Post date: [April 15, 2021, 4:40pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/19 "2021-04-15T16:40:52Z")

</div>

Inspired by @mbauman solution I think that this is my solution.

```julia
function srange(dx,xmax)
          n = ceil(2*xmax/dx) |> Int
          n = isodd(n) ? n : n+1
         range(-xmax, xmax, length=n)
 end

```

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [April 15, 2021, 4:44pm UTC](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344/20 "2021-04-15T16:44:57Z")

</div>

Note, though, that won’t always hit zero exactly. Not sure if that’s important.

[Next page](https://discourse.julialang.org/t/how-to-create-a-range-centered-around-zero/59344.md?page=2)
