【发布时间】:2014-11-27 22:02:57
【问题描述】:
在 F# 中,如何编写通用数学步进函数?
一个 (Oliver) Heaviside 阶跃函数是一个函数,如果 x 为负数则返回零,否则返回一。
这是我迄今为止的尝试总结:
// attempt 1:
let inline stepFct1< ^T when ^T : (static member op_GreaterThan: ^T * float -> bool)
> (x:^T) : ^T =
//if (^T : (static member op_GreaterThan) (x 0.0) ) then x //ouch fails also
if (>) x 0.0 then x
else 0.0
编译器说:错误FS0001:类型参数缺少约束'当^T:比较'
// attempt 2:
let inline stepFct2<^T when ^T : (static member (>): ^T * ^T -> bool) > (x:^T) : ^T =
match x with
| x when x > 0.0 -> 1.0
| 0.0
FSC 说:错误 FS0010:模式中出现意外的中缀运算符
动机:
我正在尝试重写 Ian 的 Cumulative-Normal 和 Black-Scholes 函数 here 以使用自动微分 (DiffSharp)。 Ian 的累积法线适用于浮点数,我想要一个适用于 any 数字类型的通用版本,包括 AutoDiff.DualG。 累积法线函数包含“大于”语句。
编辑:Gustavo,谢谢,我已接受您的回答 - 现在可以编译简单的 step 函数。
但它似乎对累积正常情况没有帮助。 鉴于此代码:
// Cumulative Normal Distribution Function - attempt to write a generic version
let inline CDF(x:^T) : ^T =
let (b1,b2,b3) = (0.319381530, -0.356563782, 1.781477937)
let (b4,b5) = (-1.821255978, 1.330274429)
let (p , c ) = (0.2316419 , 0.39894228)
let (zero, one) = (LanguagePrimitives.GenericZero, LanguagePrimitives.GenericOne)
if x > zero then
let t = one / (one + p * x)
(one - c * exp( -x * x / 2.0)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1))
else
let t = 1.0 / (one - p * x)
(c * exp( -x * x / 2.0)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1))
FSI 说:
C:\stdin(116,32): warning FS0064: This construct causes code to be less generic
than indicated by the type annotations.
The type variable 'T has been constrained to be type 'float'.
val inline CDF : x:float -> float
> CDF 0.1M;;
CDF 0.1M;;
----^^^^
C:\stdin(122,5): error FS0001: This expression was expected to have type
float
but here has type
decimal
>
有人知道如何使 CDF 通用吗?
【问题讨论】:
-
您的更新确实是一个新问题,但您错过了答案的重点。如果您在任何地方都有浮点文字,则代码不再是通用的。您将需要找到构造常量的通用方法。
-
@JohnPalmer 是对的,这更具挑战性。我提到的库提供了一种使用有理数作为输入并将它们转换为目标类型的方法。请参阅答案中的更新。
标签: generics math f# diffsharp