我有一个函数可以生成一定范围内的双精度数:
let gen_doublein =
fun mx mn -> Arb.generate<float> |> Gen.suchThat ( (>) mx ) |> Gen.suchThat ( (<) mn )
Run Code Online (Sandbox Code Playgroud)
然后是一个函数来生成其中 2 个数组:
let gen_params:Gen<double array> =
gen { let! x = gen_doublein 0.0 20000.0
let! y = gen_doublein 0.0 2000.0
return [| x;y|] }
Run Code Online (Sandbox Code Playgroud)
我放:
static member arb_params = Arb.fromGen gen_params
Run Code Online (Sandbox Code Playgroud)
在 Generator 类中并注册它。一切看起来都不错。为了测试这是否一切正常,我有:
let f2 (xs:double array) :double= exp (-2.0*xs.[0]) + xs.[1]*exp (-2.0*xs.[0])
let fcheck fn xs = fn xs > 0.0
Run Code Online (Sandbox Code Playgroud)
然后使用数组生成器“arrayOfLength”:
Check.Quick (Prop.forAll (arrayOfLength 2) (fcheck f2))
Run Code Online (Sandbox Code Playgroud)
但是,按预期工作:
Check.Quick (Prop.forAll (Generators.arb_params) (fcheck f2))
Run Code Online (Sandbox Code Playgroud)
刚开始做一些计算就再也没有回来。f# 大师请帮忙。
我没有尝试这个,但我认为问题是生成器float随机创建值,然后检查它们是否与您指定的谓词(范围)匹配。这意味着它必须先生成大量浮点数,然后才能(随机)生成匹配的浮点数。
float通过生成[0 .. 1] 范围内的值
,然后重新调整它们以匹配您需要的范围,可以更轻松地生成指定范围内的值。
我对 FsCheck 不太熟悉,所以我不知道是否有 [0 .. 1] 浮点范围的生成器,但您可以从生成整数并将其转换为浮点数开始:
let gen_doublein mx mn = gen {
let! n = Arb.generate<int>
let f = float n / float Int32.MaxValue
return mx + (f * (mn - mx)) }
Run Code Online (Sandbox Code Playgroud)
编辑我看到你已经解决了问题。我认为我发布的解决方案可能仍然适用于较小的范围(随机生成器不能很快产生足够的匹配值)。