F# F中带浮点(双类型)的模式匹配#
有人能解释为什么F#似乎不喜欢模式加工表达式中的float(type Double)吗F# F中带浮点(双类型)的模式匹配#,f#,floating-point,pattern-matching,double,F#,Floating Point,Pattern Matching,Double,有人能解释为什么F#似乎不喜欢模式加工表达式中的float(type Double)吗 让intDiv x y= 将x/y与 |5->printfn“结果是五个祝贺”;5. |z->printfn“结果是另一个:%i”z;Z 匹配inttype:按预期工作 让floatDiv x y= 将x/y与 |nan->printfn“伙计,你到底做了什么?”;楠 |无限->打印fn“哇,你得到了无限!”;无穷 |5.0->printfn“结果是5-为你感到骄傲”;5 |z->printfn“结果是另一
让intDiv x y=
将x/y与
|5->printfn“结果是五个祝贺”;5.
|z->printfn“结果是另一个:%i”z;Z
匹配int
type:按预期工作
让floatDiv x y=
将x/y与
|nan->printfn“伙计,你到底做了什么?”;楠
|无限->打印fn“哇,你得到了无限!”;无穷
|5.0->printfn“结果是5-为你感到骄傲”;5
|z->printfn“结果是另一个:%i”z;Z
这里匹配的casenan
每次都会匹配,编译器也会警告我这一点,但是,它似乎也会返回正确的结果。我只希望它与最后一个案例相匹配
>floatDiv 10。3.
伙计,你到底做了什么?
val it:float=3.333
正如您所观察到的nan
和infinity
在这里被视为标识符,并且值与它们绑定
如果检查F#规格:
第7章(第115页)说,const
表达式是一种模式
第4章(第36页)说,const
包括ieee64
第3章(第29页)说,ieee64
要么是一个float
,要么是一个后跟LF
在示例位置,我们找到了float
的定义
token float =
digit+ . digit*
digit+ (. digit* )? (e|E) (+|-)? digit+
此定义仅适用于123、3.14、1E99等情况。它不包括无穷大和nan
因此,根据规范,上述行为是预期的。应该改变吗?但可能需要更新语言,将nan和infinity作为float常量表达式的一部分。由于ieee确实包含了这些值,所以我认为它应该是常量表达式的一部分
然而,这种更改可能有风险,因为在旧代码nan
中突然意味着对方法的引用,随着更改,它将是一个浮点文本。也许有人用nan作为函数名?这将导致崩溃,因为这就像给一个函数命名:0
正如@傻瓜所提到的,您可以使用活动模式来解决这个问题
// Define the Active Pattern
let (|Float|Infinity|NaN|) n =
if System.Double.IsPositiveInfinity n then Infinity true
elif System.Double.IsNegativeInfinity n then Infinity false
elif System.Double.IsNaN n then NaN
else Float n
// We can then use the Active Pattern as a "smart" pattern
let floatDiv x y =
match x / y with
| NaN -> printfn "Homie, what did you even do?"; nan
| Infinity _ -> printfn "Wow, you got infinity!"; infinity
| Float 5.0 -> printfn "Result was 5 - proud of you"; 5.0
| Float z -> printfn "Result was something else: %f" z; z
let run () =
floatDiv 1.0 2.0 |> printfn "%A"
floatDiv 5.0 1.0 |> printfn "%A"
floatDiv 1.0 0.0 |> printfn "%A"
floatDiv 0.0 0.0 |> printfn "%A"
将浮点数与特定的数字进行比较总是有点“危险”,因为浮点数的性质通常只是一个近似的答案。通常将结果与公差范围进行比较
此外,;nan使许多开发人员感到困惑,因为大多数涉及nan的比较都是错误的
1.0 < nan // false <-|
nan < 1.0 // false, <-| these inequalities can break balanced trees algorithms if you use float as a key and happen to insert a nan
nan = nan // false <-|
nan <> nan // true <-| perhaps also surprising?
1.0nan
匹配为变量名,而不是浮点常量。这是语言中bug的预期行为吗?您需要这样的东西:let(| NaN | | |)value=如果Single.IsNaN value,那么Some()其他无