# How to test if one float is an integer multiple of another?

**URL:** <https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745>\
**Category:** General Usage\
**Tags:** question, float\
**Created:** [November 1, 2021, 4:00pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745 "2021-11-01T16:00:24Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jewh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jewh/32/28586_2.png) [@jewh](https://discourse.julialang.org/u/jewh)\
**Post date:** [November 1, 2021, 4:00pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/1 "2021-11-01T16:00:24Z")

</div>

What is the best way to test if one floating point number is an integer multiple of another floating number? e.g. I want this to return true for 5.5 / 0.5, and false for 5.5 / 0.6.

Naively I would expect to do this by testing for remainder 0 after division using %, i.e.

```julia
0.2 % 0.1 == 0.0 true
0.21 % 0.1 == 0.0 false

```

This works on some numbers, but fails on others, presumably due to the magic of floating point precision:

```julia
0.3 % 0.1 = 0.09999999999999998 # should be 0.0

```

What’s the most accurate, and/or simplest, way to test this?

---

<div class="post-metadata">

**Author:** ![jewh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jewh/32/28586_2.png) [@jewh](https://discourse.julialang.org/u/jewh)\
**Post date:** [November 1, 2021, 4:09pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/2 "2021-11-01T16:09:13Z")

</div>

Worth noting I don’t know the numerator or denominator a priori so cannot use `Rational` type, though this gives the correct answer

```julia
3//10 % 1//10 = 0//1

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [November 1, 2021, 4:16pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/3 "2021-11-01T16:16:46Z")

</div>

The moment you represent your numbers in floating point, it’s already too late. The number 1/10 cannot be represented in binary floating point with any finite precision for the same reason that 1/3 cannot be represented in any finite precision decimal value (they’re both just infinitely repeating fractions in their respective bases).

You can use `Rational` numbers, which will give you the exact right answer.

But if you’re somehow stuck with floating-point inputs, then you’re going to have to make up your own tolerances. For example, you could check something like:

```julia
julia> check(a, b) = isapprox(round(b / a) * a, b)
check (generic function with 1 method)

julia> check(0.1, 0.2)
true

julia> check(0.1, 0.25)
false

julia> check(0.1, 0.3)
true

```

Of course, this has edge cases too:

```julia
julia> check(0.1, 0.0) # should be true, and is
true

julia> check(0.1, 1e-16) # what should this be? Not obvious...
false

julia> check(0.1 + 1e-16, 0.2) # seems like this should match the one above...
true

```

What is preventing you from taking exact rational inputs if you actually want exact numerical results here?

---

<div class="post-metadata">

**Author:** ![jewh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jewh/32/28586_2.png) [@jewh](https://discourse.julialang.org/u/jewh)\
**Post date:** [November 1, 2021, 4:38pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/4 "2021-11-01T16:38:26Z")

</div>

Okay thanks, makes sense.

Strictly speaking nothing is preventing me from taking exact rational inputs, but I was just interested in the best way to handle this problem given an arbitrary collection of floating-point numbers.

For the specific example I have in mind though I’m taking elements in a range object e.g. `0:0.01:1` and testing them with another number, so this would be amenable to rationals.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [November 1, 2021, 8:44pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/5 "2021-11-01T20:44:07Z")

</div>

One thing that might help you here is the `rationalize` function. E.g.

```julia
julia> rationalize(0.3) % rationalize(0.1)
0//1

```

But not always. As @rdeits correctly said, “The moment you represent your numbers in floating point, it’s already too late.”

---

<div class="post-metadata">

**Author:** ![Bardo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bardo/32/21601_2.png) [@Bardo](https://discourse.julialang.org/u/Bardo)\
**Post date:** [November 2, 2021, 3:14pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/6 "2021-11-02T15:14:18Z")

</div>

`rationalize` is mathematically strict and chokes on pi.  
The following variant uses it differently:

```julia
function ismult(x,y)
    (x, y) = x < y ? (y, x) : (x, y)
    # numerator(rationalize(x/y % 1)) == 0
    # or simply
    x/y % 1 == 0
end

ismult(pi, 1e6*pi) == true

```

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [November 2, 2021, 3:40pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/7 "2021-11-02T15:40:48Z")

</div>

What do you mean by ‘chokes’? Are you referring to this `MethodError`?

```julia
julia> rationalize(pi)
ERROR: MethodError: no method matching rationalize(::Irrational{:π})
Closest candidates are:
  rationalize(::Type{T}, ::AbstractFloat; tol) where T<:Integer at rational.jl:216
  rationalize(::Type{T}, ::AbstractFloat, ::Real) where T<:Integer at rational.jl:156
  rationalize(::AbstractFloat; kvs...) at rational.jl:217
  ...
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1

```

You can only sensibly rationalize a concrete floating-point representation of `pi`:

```julia
julia> rationalize(1.0pi)
165707065//52746197

julia> rationalize(big(1.0)pi)
2646693125139304345//842468587426513207

julia> rationalize(1.0f0*pi)
355//113

```

---

<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:** [November 2, 2021, 4:02pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/8 "2021-11-02T16:02:35Z")

</div>

> [@stillyslalom](#):
>
> ```julia
> julia> rationalize(pi)
> ERROR: MethodError: no method matching rationalize(::Irrational{:π})
> 
> ```

Here is a [bug fix](https://arxiv.org/abs/2008.07995):

```julia
Base.rationalize(::Irrational{:π}) = 22//7

```

---

<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:** [November 2, 2021, 9:01pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/9 "2021-11-02T21:01:57Z")

</div>

Another suggestion that hope it is ok:

```julia
function aremultiples(a, b; ϵ=1e-16)
    (abs(a) > abs(b)) && ((a, b) = (b, a))
    (a == 0) && (return true)
    x = b/a
    abs(a*(x - round(x))) < ϵ
end

# TESTS:
aremultiples(0.1, 0.3) # true
aremultiples(0.1, 0.0) # true
aremultiples(0.1, 1e-16) # true
aremultiples(0.1 + 1e-16, 0.2) # false

aremultiples(1, -4) # true
aremultiples(1, pi) # false
aremultiples(0, 0) # true

```

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [November 2, 2021, 10:09pm UTC](https://discourse.julialang.org/t/how-to-test-if-one-float-is-an-integer-multiple-of-another/70745/10 "2021-11-02T22:09:36Z")

</div>

`aremultiples(a,b) = isapprox(rem(a, b, RoundToNearest) , 0; atol=0.01)`?
