谁能解释为什么F#在模式处理表达式中似乎不喜欢浮点数(Double类型)?
let intDiv x y =
match x / y with
| 5 -> printfn "Result was five - congrats"; 5
| z -> printfn "Result was something else: %i" z; z
匹配int
类型:按预期工作。
let floatDiv x y =
match x / y with
| nan -> printfn "Homie, what did you even do?"; nan
| infinity -> printfn "Wow, you got infinity!"; infinity
| 5.0 -> printfn "Result was 5 - proud of you"; 5.0
| z -> printfn "Result was something else: %i" z; z
这里,匹配大小写nan
每次都会匹配,并且编译器也会对此警告我-但是,它似乎也会返回正确的结果。我只希望它与最后一种情况z
相匹配。
> floatDiv 10. 3.;;
Homie, what did you even do?
val it : float = 3.333333333
答案 0 :(得分:2)
如您所见,<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On AllowOverride All
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>
和nan
在这里被视为标识符,并且值绑定到它们。
如果检查F#规范:https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf
第7章(第115页)说infinity
表达式是一种模式。
第4章(第36页)说const
包括const
。
第3章(第29页)说ieee64
是ieee64
或整数后跟float
在示例位置,我们找到了LF
的定义。
float
此定义仅涵盖123、3.14、1E99等情况。它既不包含无穷也不包含nan。
因此,按照规范,上述行为是预期的。应该改变吗?也许但涉及到更新语言以将nan和infinity包含为float常量表达式的一部分。由于token float =
digit+ . digit*
digit+ (. digit* )? (e|E) (+|-)? digit+
确实包含这些值,因此我认为它应该成为常量表达式的一部分是有意义的。
但是,更改可能有风险,因为旧代码ieee
中的突然更改意味着对方法的引用,更改将是浮点文字。也许有人用nan作为函数名?现在那样会崩溃,因为这就像给一个函数命名:nan
。
如@Foole所述,您可以使用活动模式来解决此问题。
0
将浮点数与特定数字进行比较总是有点“风险”,因为浮点数的性质通常只是一个近似的答案。通常,将结果与公差范围进行比较。
此外; nan使许多开发人员感到困惑,因为涉及nan的大多数比较都是错误的。
// 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"