# Why does 16//1 and 16.0 not equal 16 in for loop?

I am getting some behavior I can not explain. The context is that a chamber gets 9/16’ths of its content emptied, initially air. Then the 9/16ths that were removed are replaced with some pure gas. This process is repeted, and I wanted to find out how fast one starts getting pure gas. So I wrote the following script, and included a sanity-check that the air part `a` plus the gas part `g` always sum to 16. But the boolean comparison failed in the following three versions of the script:
Normal division, comparison with 16 as Int:

``````julia> begin
a = 16
g = 0
counter = 0
for i in 1:2
a *= 7/16
g *= 7/16
g += 9
counter +=1
if a+g !== 16
println("Error! \$a+\$g=\$(a+g) does not equal 16.")
#error("Gas parts do not sum to 16")
end
println("Iteration \$counter:\nGas to air ratio = \$(round(g/a, sigdigits=3))\n\n")
end
end
Error! 7.0+9.0=16.0 does not equal 16.
Iteration 1:
Gas to air ratio = 1.29

Error! 3.0625+12.9375=16.0 does not equal 16.
Iteration 2:
Gas to air ratio = 4.22
``````

Even though

``````julia> 0.005+15.995
16.0

julia> 0.005+15.995 == 16
true
``````

Rational division, comparison with 16 as Int:

``````julia> begin
a = 16
g = 0
counter = 0
for i in 1:2
a *= 7//16
g *= 7//16
g += 9
counter +=1
if a+g !== 16
println("Error! \$a+\$g=\$(a+g) does not equal 16.")
#error("Gas parts do not sum to 16")
end
println("Iteration \$counter:\nGas to air ratio = \$(round(g/a, sigdigits=3))\n\n")
end
end
Error! 7//1+9//1=16//1 does not equal 16.
Iteration 1:
Gas to air ratio = 1.29

Error! 49//16+207//16=16//1 does not equal 16.
Iteration 2:
Gas to air ratio = 4.22
``````

Even though

``````julia> 16//1==16
true
``````

Rational division, comparison with 16 as float:

``````julia> begin
a = 16
g = 0
counter = 0
for i in 1:2
a *= 7//16
g *= 7//16
g += 9
counter +=1
if a+g !== 16.0
println("Error! \$a+\$g=\$(a+g) does not equal 16.")
#error("Gas parts do not sum to 16")
end
println("Iteration \$counter:\nGas to air ratio = \$(round(g/a, sigdigits=3))\n\n")
end
end
Error! 7//1+9//1=16//1 does not equal 16.
Iteration 1:
Gas to air ratio = 1.29

Error! 49//16+207//16=16//1 does not equal 16.
Iteration 2:
Gas to air ratio = 4.22
``````

The only successful version was without rationals, and where 16 was defined as a float as opposed to an int:

``````julia> begin
a = 16
g = 0
counter = 0
for i in 1:2
a *= 7/16
g *= 7/16
g += 9
counter +=1
if a+g !== 16.0
println("Error! \$a+\$g=\$(a+g) does not equal 16.")
#error("Gas parts do not sum to 16")
end
println("Iteration \$counter:\nGas to air ratio = \$(round(g/a, sigdigits=3))\n\n")
end
end
Iteration 1:
Gas to air ratio = 1.29

Iteration 2:
Gas to air ratio = 4.22
``````

I can not explain why they dont all evaluate to `true`. Can you help me understand?

1 Like

`!==` == `!(===)`. It checks whether the two values are identical (i.e. inseparable by the computer). You’re looking for `!=`.

6 Likes

Oh snap you’re right! My bad. Thanks!

But it’s not just about `!=` vs `!==`. You shouldn’t have conditions depend on floating point comparisons, since you will very frequently run into floating point inaccuracies.

4 Likes

What about using `isapprox`?

1 Like

Yes.

1 Like

Right. That was one of the things I was checking for by printing the sum. But as a general principle, you are right, `isapprox` is better suited. I just looked up the docstring and realized that the default tolerances for `isapprox` are actually set just right for comparison of floating point numbers. Thanks!

I felt like the difference between `!==` and `!=` was the more pressing question, but yes, this is better.

`≈` is another way to write `isapprox`.

1 Like