比较浮动列表

时间:2010-10-22 14:40:21

标签: ocaml

我写了一段代码:

let rec compareVs v1 v2 =
 if List.length v1 == 0 then
  true
 else
  ((match v1 with [] -> 0. | h::l -> h) == (match v2 with [] -> 0. | h::l -> h)) && 
  (compareVs(match v1 with [] -> [] | h::l -> l) (match v2 with [] -> [] | h::l -> l))

然后跑了:

# compareVs [0.1;0.1] [0.1;0.1];;
- : bool = false

似乎无法找到问题所在。请帮忙。

修改

问题与浮动比较有关:

# 0.1 == 0.1;;
- : bool = false
# 1.0 == 1.0;;
- : bool = false

我们如何比较ocaml中的浮点数?

2 个答案:

答案 0 :(得分:11)

使用=,而不是==

浮点数是ocaml中的引用类型,==检查引用相等性。所以0.1 == 0.1是假的。

通常,您几乎总是希望使用=而不是==来比较两个值。

请注意,除此之外,您的函数将返回true两个不同大小的列表。假设这不是你想要的,你应该只在两个列表为空时返回true,而当其中一个列表为空而另一个列表为空时返回false。

作为样式注释,使用List.length检查列表是否为空通常是一个坏主意(一方面它是O(n),即使它可以在模式匹配的O(1)中完成。在开头使用模式匹配也会稍微清理你的代码。

像这样:

let rec compareVs v1 v2 = match v1, v2 with
| [], []       -> true
| [], _
| _, []        -> false
| x::xs, y::ys -> x = y && compareVs xs ys

哦,如果这不仅仅是一个练习,请注意你可以做v1 = v2而实际上不需要为此编写一个函数。

答案 1 :(得分:5)

Sepp2k是正确的,但作为关于比较浮动(通常是危险的)的额外讨论,以下功能对我有所帮助:

这比较了两个具有epsilon容差的浮点数,语法与其他浮点函数类似。明显延伸>.和其他人显而易见。

let epsilon = 1.0e-10
let (=.) a b = (abs_float (a-.b)) < epsilon

如果您正在处理浮动的许多极端值,您应该查看classify_float function in the pervasives module。我不记得在NAN函数中如何比较=值。如果需要,您可以单独试验。

我已经使用了一段时间了,但是它的容差实际上对我的使用率来说很低(例如,epsilon的一个非常小的值,如上所述)。这没有考虑到NAN-NAN的作用。所以,这可能没用。

    let (=.) a b = match classify_float ( a -. b ) with
        | FP_infinite  | FP_nan | FP_normal -> false
        | FP_subnormal | FP_zero -> true