Why is 0.0 == 0.0 false in REPL but true when executing natively?

  • A+

0.0 == 0.0 is false when I execute that expression in the interactive REPL:

$ ocaml         OCaml version 4.02.3  # 0.0 == 0.0;; - : bool = false # 0.0 = 0.0;; - : bool = true 

But it's true if I compile and run this program:

let _ =                                                                                                                                                                                                                                                                     print_endline (string_of_bool (0.0 == 0.0));   print_endline (string_of_bool (0.0 = 0.0)) 

dune file:

(executable (name main)) 

Compiling and running it:

$ dune --version 1.0.0 $ dune exec ./main.exe true true 

How could 0.0 == 0.0 ever be false, and why would it be a different value when executing this code natively?


Note for OCaml beginners: the "normal" equality is =. The == operator tests if two value have the same memory address.

The == operator is sometimes quite hard to understand. To quote the OCaml manual:

On non-mutable types, the behavior of ( == ) is implementation-dependent; however, it is guaranteed that e1 == e2 implies compare e1 e2 = 0.

float being a non-mutable type, there is no guarantee of its behavior on two equal values.

Now, let's see exactly what happens.

In the case of the interpreter, your expressions are evaluated without much optimization. The point is to put your code to execution quickly, not to have your code run fast. So when it sees a 0.0 constant, the programs allocates a new physical memory block that contains the appropriate data "float 0.0". Allocate the same constant two times and you get two different memory addresses. Hence a 0.0 == 0.0 returns false

Now the native code compiler is much more smarter. It tries to minimize memory usage and execution time. When it sees that the same immutable constant is allocated two times, it considers "there is no point in allocating the same thing twice, let's allocate once".

In a way, the compiler turns 0.0 == 0.0 in let c = 0.0 in c == c. This is why you get true.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: