Pig*_*tta 0 generics math f# diffsharp
在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
Run Code Online (Sandbox Code Playgroud)
编译器说:错误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
Run Code Online (Sandbox Code Playgroud)
FSC说:错误FS0010:模式中出现意外的中缀运算符
动机:
我试图改写伊恩的累积正常和布莱克-斯科尔斯的功能在这里使用自动分辨(DiffSharp).Ian的Cumulative Normal适用于浮点数,我想要一个适用于任何数字类型的通用版本,包括AutoDiff.DualG.累积正常函数包含"大于"语句.
编辑:古斯塔沃,谢谢,我接受了你的回答 - 简单的步骤函数现在编译.
但它似乎没有帮助累积正常情况.鉴于此代码:
// 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))
Run Code Online (Sandbox Code Playgroud)
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
>
Run Code Online (Sandbox Code Playgroud)
有谁知道如何使CDF通用?
使用LanguagePrimitives.GenericZero
/ GenericOne
并让类型推断完成其余的工作
// attempt 1:
let inline stepFct1 x =
let zero = LanguagePrimitives.GenericZero
if x > zero then x
else zero
Run Code Online (Sandbox Code Playgroud)
我查看了您要使用要实现的功能发送的链接.FSharpPlus(F#+)可以帮助您编写通用数学代码,因为它包含专用的通用数字模块.或者至少你可以从中获取一些技术.
UPDATE
关于更新问题,将复杂性提升到更高水平,这是使用最新版F#+项目的解决方案:
let inline CDF(x:^T) : ^T =
let num x = fromRational (x </ratio/> 1000000000I)
let (b1,b2,b3) = (num 319381530I , num -356563782I , num 1781477937I)
let (b4,b5) = (num -1821255978I , num 1330274429I)
let (p , c ) = (num 0231641900I , num 0398942280I)
let (zero, one, two) = 0G, 1G, 2G
if x > zero then
let t = one / (one + p * x)
(one - c * exp( -x * x / two)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1))
else
let t = one / (one - p * x)
(c * exp( -x * x / two)* t * (t*(t*(t*(t*b5+b4)+b3)+b2)+b1))
Run Code Online (Sandbox Code Playgroud)
不幸的是,此时我意识到一些函数在库中被标记为内部,因此没有公开,但是我在这里的一个工作示例中重新创建了它们,这样你就可以测试你的函数,它可以很好地用于float
和float32
.
新版本将在今年年底之前发布,但同时您可以分支它,删除内部并编译它,或者只是像我在链接示例中那样重新创建函数.
如果您对Generic Maths感兴趣,请随时提供代码或用例.