我正在学习Jason Hickey 的 Objective Caml 简介。
它说
Matching against floating-point values is supported, but it is rarely used because of numerical issues
好的,我们无法匹配浮点值。
那如果我们需要呢?那怎么办呢?
我正在学习Jason Hickey 的 Objective Caml 简介。
它说
Matching against floating-point values is supported, but it is rarely used because of numerical issues
好的,我们无法匹配浮点值。
那如果我们需要呢?那怎么办呢?
您可以匹配浮点数,它只是说它很少使用。
它很少使用,因为可能会出现精度问题。如果您有两个数字 x 和 y:
x = 0.000000001
y = 0.0000000009
x 和 y 一样吗?这要看情况。如果 x 和 y 是计算结果,那么累积舍入可以解释差异,它们可能是相同的。
更粗略地说,浮点比较通常“足够接近”,因此为什么模式匹配很少使用它们作为精确匹配可以排除经常需要的“足够接近”匹配。
您可以编写带有辅助函数的模式保护来检查是否相等,或者是否符合某些 epsilon 或其他标准。
要扩展以前的答案,您可以将模式匹配与浮点数结合使用,如下例所示:
# let float_match_example = function
| 0. -> "exact zero"
| x when abs_float x < 1e-12 -> "epsilon"
| _ -> "other";;
val float_match_example : float -> string = <fun>
# List.map float_match_example [0.; 42e-15; 3.];;
- : string list = ["exact zero"; "epsilon"; "other"]
请注意,模式匹配隐式使用相等测试,这在使用浮点数时很少需要:当舍入误差累积时,两个浮点数很少完全相等。因此,您可以使用带有关键字的守卫when
,如上面的代码所示。
当您使用代数数据类型(如Some 3: int option
)时,实际上需要模式匹配。这是获取包含值的基本 OCaml 功能。当使用像数字这样的原始值时,模式匹配只是一种方便的表示法。可以使用常用的关系运算符(和if
语句)。这就是您通常用于浮点值的方法。正如其他人所提到的,您还可以使用模式保护,这主要是另一种形式的if
陈述。