我写了一段代码:
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中的浮点数?
答案 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