Julia Language Testing Floating Point Approximate Equality


Example

What's the deal with the following?

julia> @test 0.1 + 0.2 == 0.3
Test Failed
  Expression: 0.1 + 0.2 == 0.3
   Evaluated: 0.30000000000000004 == 0.3
ERROR: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
 in do_test(::Base.Test.Returned, ::Expr) at ./test.jl:281

The error is caused by the fact that none of 0.1, 0.2, and 0.3 are represented in the computer as exactly those values — 1//10, 2//10, and 3//10. Instead, they are approximated by values that are very close. But as seen in the test failure above, when adding two approximations together, the result can be a slightly worse approximation than is possible. There is much more to this subject that cannot be covered here.

But we aren't out of luck! To test that the combination of rounding to a floating point number and floating point arithmetic is approximately correct, even if not exact, we can use the isapprox function (which corresponds to operator ). So we can rewrite our test as

julia> @test 0.1 + 0.2 ≈ 0.3
Test Passed
  Expression: 0.1 + 0.2 ≈ 0.3
   Evaluated: 0.30000000000000004 isapprox 0.3

Of course, if our code was entirely wrong, the test will still catch that:

julia> @test 0.1 + 0.2 ≈ 0.4
Test Failed
  Expression: 0.1 + 0.2 ≈ 0.4
   Evaluated: 0.30000000000000004 isapprox 0.4
ERROR: There was an error during testing
 in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
 in do_test(::Base.Test.Returned, ::Expr) at ./test.jl:281

The isapprox function uses heuristics based off the size of the numbers and the precision of the floating point type to determine the amount of error to be tolerated. It's not appropriate for all situations, but it works in most, and saves a lot of effort implementing one's own version of isapprox.