# Conditional indexing issue with float precision

**URL:** <https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833>\
**Category:** General Usage\
**Created:** [August 22, 2019, 6:10am UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833 "2019-08-22T06:10:27Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 22, 2019, 6:10am UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/1 "2019-08-22T06:10:27Z")

</div>

Hi!  
I came accross a float-precision issue that I want to share and ask if there is a solution for my problem.

I define an array of coordinates, an equally-sized array for the result, and I want to fill the second array with numbers in segmentwise fashion through conditional indexing. This works fine for integer coordinates, but gets totally confusing (for me) with float coordinates.  
I realize, isapprox points into the right direction, but its not fixing the issue entirely.

Here’s my code

```julia
#integer version
x = 0:1:20
seg_size = 2
seg_period = 4

I = zeros(Int64,size(x))
I[((x .% seg_period).>=0) .& ((x .% seg_period).<seg_size)] .= 2
I[((x .% seg_period).>=seg_size) .& ((x .% seg_period).<seg_period)] .= 1
println(I)

#float version
x = 0:.025:.5
seg_size = .05
seg_period = .1

I = zeros(Int64,size(x))
I[((x .% seg_period).>=0) .& ((x .% seg_period).<seg_size)] .= 2
I[((x .% seg_period).>=seg_size) .& ((x .% seg_period).<seg_period)] .= 1
println(I)

#float with isapprox
I = zeros(Int64,size(x))
I[(((x .% seg_period).>0) .| ((x .% seg_period).≈0)) .& ((x .% seg_period).<seg_size)] .= 2
I[(((x .% seg_period).>seg_size) .| ((x .% seg_period).≈seg_size)) .& ((x .% seg_period).<seg_period)] .= 1
println(I)

```

output:  
[2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2]  
[2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1, 1]  
[2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1]

The integer version (first output line) is nicely alternating between 1 and 2, which is the expected result.  
The float version (second output line) has several mis-assignments due to float precision.  
The float version using isapprox (third output line) can solve some issues, where the \>= condition failed due to float precision, but cannot solve the issue where the \< condition becomes true although the arguments are approximately equal.

So my question:

- Is there any better way to do things like that while keeping the code quite readable?
- Is there or should there be a approximate-version of \>, \<, \>=, \<= so that such an example (with appearantly very simple numbers) would work as naively expected?

Looking forward to your suggestions.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 22, 2019, 7:04am UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/2 "2019-08-22T07:04:43Z")

</div>

This is to be expected because of floating point error:

> [@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…

If there is an outcome for a calculation that follows from theory, you should generate that directly.

---

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 22, 2019, 2:01pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/3 "2019-08-22T14:01:01Z")

</div>

Hi Tamas\_Papp,  
thank you for your quick reply.

In fact, I’m fully aware that this is a limitation of the floating point representation and not a Julia bug!

However, the question is, how do I better address segments on a floating-point coordinate system without gaps and without deviations in segment width?

I cannot fully understand your last sentence suggestion.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 22, 2019, 2:16pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/4 "2019-08-22T14:16:25Z")

</div>

I don’t understand what you are trying do, since

```julia
(x .% seg_period) .< seg_period

```

should always be true in theory by construction, and when it isn’t, that’s just floating point error.

In this particular case, having non-exactly representable numbers on the boundary is also problematic, so could use rational numbers.

```julia
classify(x, seg_period, seg_size) = (x % seg_period) < seg_size ? 2 : 1
classify.(0:1:20, 4, 2)
classify.(0:(1//40):(1//2), 1//10, 1//20)

```

---

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 22, 2019, 2:47pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/5 "2019-08-22T14:47:50Z")

</div>

Thanks.

You are right that the quoted condition doesnt make sense… The example is of coarse simplified and some sense got lost in this process. However, if you remove the quoted condition, the outcome of all 3 versions is still different.

You’re example pretty much answers my question. I’ll give it a try.  
Thank you!

---

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 24, 2019, 9:20am UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/6 "2019-08-24T09:20:23Z")

</div>

Hi,

I figured out another workaround: just defining comparison operators taking into account approximate equality:

```julia
 (≲)(x,y) = <(x,y) | ≈(x,y)
 (⋦)(x,y) = <(x,y) & !≈(x,y)
 (≳)(x,y) = >(x,y) | ≈(x,y)
 (⋧)(x,y) = >(x,y) & !≈(x,y)

```

So, replacing \>= by ≳ and \< by ⋦ seems to make the range examples work with floats work as expected for rationals/integers.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [August 24, 2019, 11:13am UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/7 "2019-08-24T11:13:42Z")

</div>

> [@drhouse82](#):
>
> replacing \>= by ≳ and \< by ⋦ seems to make the range examples work with floats work as expected for rationals/integers.

This may fix operations which should “seemingly work” (eg 0.3 \cdot 3 = 9, while with `Float64` you have `0.3 * 3 !== 9`), but depending on your input and what is “expected”, you could find examples where it does not work.

If you want exact arithmetic for rationals, you should just use rationals.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [August 24, 2019, 11:30am UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/8 "2019-08-24T11:30:22Z")

</div>

In the example you give, values follow the following properties:

- the range step (0.025) is not exactly represent able as a float
- neither is the value assigned to `seg_size` but it is a multiple of the range step
- the value `seg_period` is both representable and a multiple of the range step

Are those properties true in your real use case, or is it only true of your simplified MWE here?  
If in particular it is always true that `seg_size` and `seg_period` are multiples of the range size, then you could (and should) only work with integers.

If, on the other hand, these properties do not hold in your real application (eg x values are not equally spaced), then your MWE might not be representative enough.

A key question here is: how often does it happen that one element of x falls right on the boundary between two segments? And can these situations be known in advance?

---

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 24, 2019, 12:45pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/9 "2019-08-24T12:45:26Z")

</div>

I agree that there are likely examples that still dont work “as expected”.

With regard to my problem: I try to model a physical experiment.

- So usually range steps are dictated by the experiment but could of course (inconveniently) be mapped to integers.
- seg\_size is not necessarily multiple of the range step.
- seg\_period is also given by the real-world experiment and cannot be freely chosen.

Trying to answer your key question: as long as I dont think about the numerics, to me it makes intuitive sense to have any kind of segments start and end at an coordinate. In a floating-point numerics context, this is obviously a very bad idea.  
Maybe I have to rethink the way I approach these kinds of problems to have segment borders usually right between two coordinates.

Thanks for all your input.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [August 24, 2019, 1:02pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/10 "2019-08-24T13:02:32Z")

</div>

> [@drhouse82](#):
>
> it makes intuitive sense to have any kind of segments start and end at an coordinate.

IIUC even in your real use case x values are equally spaced?  
In that case, my intuitive sense would be to place segment boundaries right in the middle between two neighboring coordinates. But I guess it all depends on what you’re trying to achieve and you probably know better.

I would tend to think that if all your numbers come from physical measurements (or a model thereof), it should almost never happen that two numbers are equal (to machine precision) because measurement instruments (or models) tend to be affected by far higher uncertainties than 1e-15.

This is probably a very naive question, but have you checked that you actually have significant issues with floats in your real use case?

---

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 24, 2019, 6:38pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/11 "2019-08-24T18:38:20Z")

</div>

> [@ffevotte](#):
>
> I would tend to think that if all your numbers come from physical measurements (or a model thereof), it should almost never happen that two numbers are equal (to machine precision) because measurement instruments (or models) tend to be affected by far higher uncertainties than 1e-15.
> 
> This is probably a very naive question, but have you checked that you actually have significant issues with floats in your real use case?

Of course, measured values are never equal. However, especially spatial coordinates or time-information is often not measured but defined/assumed and other quantities are than measured vs. these nominal values.  
E.g., if you measure a wavefrom with an oscilloscope, the time information is float and equally spaced. It’s determined by the instruments operating frequency and settings. Time information is not measured but assumed to be correctly known. The measured voltage-values corresponding to these time points are definitively prone to measurement accuracy much worse than numerical accuracy, and comparing these for exact equality is of no sense.  
However, modelling the experiment (with identical float time-base) or accessing certain segments of the measured data by indexing the waveform with conditions involving the time-array, is a quite usual use case, I would say.

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [August 24, 2019, 8:55pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/12 "2019-08-24T20:55:10Z")

</div>

> [@drhouse82](#):
>
> spatial coordinates or time-information is often not measured but defined/assumed and other quantities are than measured vs. these nominal values.

Thanks for the explanation, that makes perfect sense.

Still, I the question remains: if neither the segment size nor the segment period are multiples of the range step, what are the odds of an element in `x` coinciding with a segment boundary?

---

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 24, 2019, 9:10pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/13 "2019-08-24T21:10:55Z")

</div>

seg\_period usually is a multiple of step size…

---

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [August 24, 2019, 10:10pm UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/14 "2019-08-24T22:10:33Z")

</div>

OK. In that case, let me reformulate your initial MWE in this way:

```julia
# x = 0:step:x_max
# x[i] = (i-1) * step
# x_max = N * step
step = 0.02;
N = 20;

# seg_size is not a multiple of step
seg_size = .05;

# ... but seg_period is
P = 5;
seg_period = P*step;

```

Then you initial implementation looks like this:

```julia
I = zeros(Int64,N+1);
for i in 1:N+1
    xi = (i-1)*step

    if xi % seg_period < seg_size
        I[i] = 2
    else
        I[i] = 1
    end
end
println(I)
# -> [2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 1, 1, 2]
# problem here ^

```

However, taking advantage of your knowledge that `seg_period` is a multiple of `step`, you know when problems will happen and avoid them:

```julia
I = zeros(Int64,N+1);
for i in 1:N+1
    xi = (i-1)*step

    if (i-1)%P == 0 || xi % seg_period < seg_size
        # if (i-1)%P==0, then (i-1)=k*P
        # => x[i] = (i-1)*step = k*P*step = k*seg_period
        # => x[i] % seg_period = 0
        I[i] = 2
    else
        I[i] = 1
    end
end
println(I)
# -> [2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2]
# no problem any more ^

```

Would something like this be applicable to your real use case?

---

<div class="post-metadata">

**Author:** ![drhouse82](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/drhouse82/32/9806_2.png) [@drhouse82](https://discourse.julialang.org/u/drhouse82)\
**Post date:** [August 26, 2019, 5:42am UTC](https://discourse.julialang.org/t/conditional-indexing-issue-with-float-precision/27833/15 "2019-08-26T05:42:18Z")

</div>

This would surely solve the problem. However, for the sake of readability, I tried to avoid having float-coordinates and integer representations of the same (either loop indices or another coordinate array). So I’ll stick to using rationals or using approximate comparisons.
