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?

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

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.

What about using isapprox?

Yes.

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.