# For loops issue

**URL:** <https://discourse.julialang.org/t/for-loops-issue/92227>\
**Category:** General Usage\
**Tags:** question\
**Created:** [December 28, 2022, 1:04pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227 "2022-12-28T13:04:03Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Allan\_Olave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_olave/32/38653_2.png) [@Allan\_Olave](https://discourse.julialang.org/u/Allan_Olave)\
**Post date:** [December 28, 2022, 1:04pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/1 "2022-12-28T13:04:03Z")

</div>

# Running the following code in julia REPL

```julia-auto
x = 1.1; h = 0.1;
x_list = [i for i in (x-2h):h:(x+2h)]

```

# Gives the following output

0.9000000000000001  
1.0000000000000002  
1.1  
1.2000000000000002

# I’m expecting the output would be the following

0.9  
1.0  
1.1  
1.2  
1.3

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 28, 2022, 1:13pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/2 "2022-12-28T13:13:12Z")

</div>

```julia-auto
julia> 1.1 - 2*0.1
0.9000000000000001

```

This is not Julia-specific, it’s due to the fact that [standard floating-point arithmetic](https://en.wikipedia.org/wiki/IEEE_754) doesn’t exactly represent decimal values like `1.1` and `0.1`. For example, in Python 3:

```py
>>> 1.1 - 2*0.1
0.9000000000000001

```

See:

> [@PSA: floating-point arithmetic](https://discourse.julialang.org/t/psa-floating-point-arithmetic/8678):
>
> Sometimes people are surprised by the results of floating-point calculations such as julia\> 5/6 0.8333333333333334 # shouldn't the last digit be 3? julia\> 2.6 - 0.7 - 1.9 2.220446049250313e-16 # shouldn't the answer be 0? These are not bugs in Julia. They’re consequences of the IEEE-standard 64-bit binary representation of floating-point numbers that is burned into computer hardware, which Julia and many other languages use by default. Brief explanation You can t…

---

<div class="post-metadata">

**Author:** ![Allan\_Olave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_olave/32/38653_2.png) [@Allan\_Olave](https://discourse.julialang.org/u/Allan_Olave)\
**Post date:** [December 28, 2022, 1:23pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/3 "2022-12-28T13:23:31Z")

</div>

my particular problem is  
The output print 4 elements  
0.9000000000000001  
1.0000000000000002  
1.1  
1.2000000000000002  
I’m expecting 5 elements  
0.9  
1.0  
1.1  
1.2  
1.3

Thanks

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [December 28, 2022, 1:26pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/4 "2022-12-28T13:26:27Z")

</div>

Try

```julia
collect(LinRange(0.9,1.3,5))

```

---

<div class="post-metadata">

**Author:** ![Allan\_Olave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/allan_olave/32/38653_2.png) [@Allan\_Olave](https://discourse.julialang.org/u/Allan_Olave)\
**Post date:** [December 28, 2022, 1:31pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/5 "2022-12-28T13:31:38Z")

</div>

It works, thank you!

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 28, 2022, 1:33pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/6 "2022-12-28T13:33:43Z")

</div>

> [@Allan\_Olave](#):
>
> I’m expecting 5 elements

This is an intrinsic problem with floating-point ranges, unfortunately — due to roundoff errors perturbing the endpoints, it can change the number of points by 1.

The solution is to explicitly specify the desired length, with `range(x-2h, step=h, length=5)`, or `range(x-2h, x+2h, length=5)`, or `LinRange(x-2h, x+2h, 5)`. (`range` and `LinRange` compute their elements in slightly different ways.)

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [December 28, 2022, 1:44pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/7 "2022-12-28T13:44:31Z")

</div>

> [@fatteneder](#):
>
> `collect(LinRange(0.9,1.3,5))`

Or `range(0.9, 1.3, 5)`. You should also consider, @Allan_Olave, whether to just drop the `collect` and leave it as a range object.

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [December 28, 2022, 2:23pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/8 "2022-12-28T14:23:32Z")

</div>

Another option is using `StepRangeLen` directly with the `offset` argument. This should be more precise than `LinRange`. (For `x = 1.1`, `h = 0.1`, it produces the same values as `LinRange`. But in other cases, it might not.)

```julia
julia> StepRangeLen(x, h, 5, 3) |> collect
5-element Vector{Float64}:
 0.9000000000000001
 1.0
 1.1
 1.2000000000000002
 1.3

julia> LinRange(x-2h, x+2h, 5) |> collect
5-element Vector{Float64}:
 0.9000000000000001
 1.0
 1.1
 1.2000000000000002
 1.3

```

`StepRangeLen` also preserves the exact `step` while `LinRange` does not:

```julia
julia> StepRangeLen(x, h, 5, 3) |> step
0.1

julia> LinRange(x-2h, x+2h, 5) |> step
0.09999999999999998

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [December 28, 2022, 2:43pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/9 "2022-12-28T14:43:45Z")

</div>

> [@sostock](#):
>
> Another option is using `StepRangeLen`

But as far as I know, this is what `range` does, and that would be the ‘user interface’ for `StepRangeLen`, instead of calling the constructor directly.

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [December 28, 2022, 3:17pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/10 "2022-12-28T15:17:15Z")

</div>

> [@DNF](#):
>
> But as far as I know, this is what `range` does, and that would be the ‘user interface’ for `StepRangeLen`, instead of calling the constructor directly.

`range` creates a `StepRangeLen` (in this case), but without using `offset`. This forces you to use `x-2h` or `x+2h` as the reference value, with possible loss of precision:

```julia
julia> range(x-2h, step=h, length=5) |> collect
5-element Vector{Float64}:
 0.9000000000000001
 1.0000000000000002
 1.1
 1.2000000000000002
 1.3000000000000003

julia> StepRangeLen(x, h, 5, 3) |> collect
5-element Vector{Float64}:
 0.9000000000000001
 1.0
 1.1
 1.2000000000000002
 1.3

```

(Note that the second and fifth elements are different.)

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [December 28, 2022, 3:59pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/11 "2022-12-28T15:59:30Z")

</div>

This is close in spirit to your original formulation but does the range with integers to ensure five elements. And you don’t need much knowledge about Julia’s range types.

```julia
julia> x = 1.1; h = 0.1;

julia> xlist = x .+ (-2:1:2)*h
0.9000000000000001:0.1:1.3

julia> collect(xlist)
5-element Vector{Float64}:
 0.9000000000000001
 1.0
 1.1
 1.2000000000000002
 1.3

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [December 28, 2022, 4:40pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/12 "2022-12-28T16:40:18Z")

</div>

> [@sostock](#):
>
> ```julia
> julia> range(x-2h, step=h, length=5) |> collect
> 5-element Vector{Float64}:
> 0.9000000000000001
> 1.0000000000000002
> 1.1
> 1.2000000000000002
> 1.3000000000000003
> 
> julia> StepRangeLen(x, h, 5, 3) |> collect
> 5-element Vector{Float64}:
> 0.9000000000000001
> 1.0
> 1.1
> 1.2000000000000002
> 1.3
> 
> ```

Try this

```julia
range(x-2h, x+2h, 5)

```

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [December 28, 2022, 6:13pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/13 "2022-12-28T18:13:44Z")

</div>

> [@DNF](#):
>
> Try this
> 
> `range(x-2h, x+2h, 5)`

This results in the same values in this specific case (`x=1.1`, `h=0.1`), but can still be less precise for other values:

```julia
julia> x = 0.7777952957598123; h = 0.9328657194781406;

julia> x ∈ range(x-2h, x+2h, 5) # shouldn’t this range contain x?
false

julia> x ∈ StepRangeLen(x, h, 5, 3)
true

julia> range(x-2h, x+2h, 5) |> collect
5-element Vector{Float64}:
 -1.087936143196469
 -0.15507042371832835
  0.7777952957598122 # this isn’t the original x …
  1.7106610152379527
  2.6435267347160933

julia> StepRangeLen(x,h,5,3) |> collect
5-element Vector{Float64}:
 -1.087936143196469
 -0.15507042371832824
  0.7777952957598123 # … but this is!
  1.7106610152379529
  2.6435267347160933

```

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [December 28, 2022, 6:28pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/14 "2022-12-28T18:28:30Z")

</div>

That is strange, because I thought this was exactly the sort of thing `range` was designed to do correctly.

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [December 28, 2022, 6:54pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/15 "2022-12-28T18:54:40Z")

</div>

I would argue it _is_ doing it correctly, it’s as precise as it can be with the information it is given.

`range(x-2h, x+2h, 5)` doesn’t know about the original `x` and `h`, it only sees the results of the computations `x-2h` and `x+2h`, both of which are not exact (due to floating-point arithmetic). Therefore, `range(x-2h, x+2h, 5)` does not necessarily create a range with step `h`, or one that contains `x`.

Of course, this loss of precision may not be important, so using `range` is perfectly fine. I just wanted to mention `StepRangeLen` with `offset` as probably the most precise option for a given `x` and `h`.

---

<div class="post-metadata">

**Author:** ![John\_Gibson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/john_gibson/32/5321_2.png) [@John\_Gibson](https://discourse.julialang.org/u/John_Gibson)\
**Post date:** [December 28, 2022, 11:35pm UTC](https://discourse.julialang.org/t/for-loops-issue/92227/16 "2022-12-28T23:35:48Z")

</div>

`x .+ (-2:2)*h` contains x exactly, another advantage.
