为什么在REPL中0.0 == 0.0为false但在本地执行时为true?

时间:2019-02-23 21:07:10

标签: floating-point ocaml

在交互式REPL中执行该表达式时,

0.0 == 0.0false

$ ocaml
        OCaml version 4.02.3

# 0.0 == 0.0;;
- : bool = false
# 0.0 = 0.0;;
- : bool = true

但是如果我编译并运行此程序,则为true

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

dune文件:

(executable (name main))

编译并运行它:

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

0.0 == 0.0会变成false,为什么在本地执行此代码时将其设为不同的值?

1 个答案:

答案 0 :(得分:11)

针对OCaml初学者的说明:“正常”的等式是===运算符测试两个值是否具有相同的内存地址。

==运算符有时很难理解。引用OCaml手册:

  

在非可变类型上,(==)的行为取决于实现。但是,可以保证e1 == e2暗示compare e1 e2 = 0

float是非可变类型,不能保证其在两个相等值上的行为。

现在,让我们确切地看看会发生什么。

对于解释器,无需太多优化即可对表达式进行求值。关键是使您的代码快速执行,而不是使代码快速运行。因此,当程序看到0.0常量时,程序将分配一个新的物理内存块,其中包含适当的数据“ float 0.0”。分配相同的常量两次,您将获得两个不同的内存地址。因此,0.0 == 0.0返回false

现在,本机代码编译器更加智能。它试图最小化内存使用和执行时间。当看到相同的不可变常量被分配了两次时,便认为“两次分配相同的对象没有意义,让我们分配一次”。

在某种程度上,编译器将0.0 == 0.0变成let c = 0.0 in c == c。这就是为什么您获得true的原因。