# How to make a Set of real values based on rtol?

**URL:** <https://discourse.julialang.org/t/how-to-make-a-set-of-real-values-based-on-rtol/11769>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 18, 2018, 11:00pm UTC](https://discourse.julialang.org/t/how-to-make-a-set-of-real-values-based-on-rtol/11769 "2018-06-18T23:00:27Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [June 18, 2018, 11:00pm UTC](https://discourse.julialang.org/t/how-to-make-a-set-of-real-values-based-on-rtol/11769/1 "2018-06-18T23:00:27Z")

</div>

Lets say you wanted to make a `Set` of real numbers:

```julia
Set( [ 
    1.0,
    1+eps(),
    2
] )

```

Where for all practical purposes, this should reduce to `Set([1.0,2.0])`

Is there an existing data structure that allows something like: `Set(..., rtol=1e-8)` to provide this functionality?

(as well as maintain all the features of a `Set`)

* * *

**edit:** I guess what I’m asking is:

- is it possible to change the equality condition for `Set` checking?

---

<div class="post-metadata">

**Author:** ![goretkin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goretkin/32/167_2.png) [@goretkin](https://discourse.julialang.org/u/goretkin)\
**Post date:** [June 18, 2018, 11:45pm UTC](https://discourse.julialang.org/t/how-to-make-a-set-of-real-values-based-on-rtol/11769/2 "2018-06-18T23:45:45Z")

</div>

`Set` is based on hashing, and there won’t be a hash function for your notion of equality, because it’s not transitive.

```julia
julia> a,b,c = [1.0 .+ i * 5e7 * eps() for i in 0:2];

julia> isapprox(a,b)
true

julia> isapprox(b,c)
true

julia> isapprox(a,c)
false

```

Because you want to do this for real numbers, which are ordered, you should be able to keep a sorted list of members. That way, it will take log(n) time to insert an element or decide it’s already inserted, instead of n time. You should be able to use `searchsorted` for this.

---

<div class="post-metadata">

**Author:** ![djsegal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/djsegal/32/13752_2.png) [@djsegal](https://discourse.julialang.org/u/djsegal)\
**Post date:** [August 6, 2018, 9:59pm UTC](https://discourse.julialang.org/t/how-to-make-a-set-of-real-values-based-on-rtol/11769/3 "2018-08-06T21:59:42Z")

</div>

Or for the simple,

```julia
function filter_approx!(cur_vector; atol=5e-2)
  delete_indices = []

  for (cur_index, cur_value) in enumerate(cur_vector)
    is_duplicate = any(
      tmp_value -> isapprox(tmp_value, cur_value, atol=atol),
      cur_vector[1:cur_index-1]
    )

    is_duplicate || continue
    push!(delete_indices, cur_index)
  end

  deleteat!(cur_vector, delete_indices)

  cur_vector
end

```

* * *

With,

```julia
tmp_vector = [1.0 .+ i * 5e7 * eps() for i in 0:2]
filter_approx!(tmp_vector)

println(tmp_vector)

```

`>> [1.0]`

* * *

Further convenience methods,

```julia
function approx_push!(cur_vector, cur_value; atol=5e-2)
  is_duplicate = any(
    tmp_value -> isapprox(tmp_value, cur_value, atol=atol),
    cur_vector
  )

  is_duplicate && return cur_vector
  push!(cur_vector, cur_value)  
end

```

```julia
function approx_append!(cur_vector, other_vector; atol=5e-2)
  append!(cur_vector, other_vector)  
  filter_approx!(cur_vector; atol=atol)

  cur_vector
end

```
