我有一个在一定范围内生成双精度数的函数:
let gen_doublein =
fun mx mn -> Arb.generate<float> |> Gen.suchThat ( (>) mx ) |> Gen.suchThat ( (<) mn )然后是一个函数,用来生成一个包含以下两个元素的数组:
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|] }我放了:
static member arb_params = Arb.fromGen gen_params在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然后使用数组生成器'arrayOfLength':
Check.Quick (Prop.forAll (arrayOfLength 2) (fcheck f2))然而,其工作方式与预期一致:
Check.Quick (Prop.forAll (Generators.arb_params) (fcheck f2))只是开始做一些计算,再也不回来了。f#大师请帮帮忙。
发布于 2012-03-21 00:09:25
我没有尝试这样做,但我认为问题在于生成器随机创建float值,然后检查它们是否与您指定的谓词(范围)匹配。这意味着它必须生成大量的浮点数,然后(随机地)生成一个匹配的浮点数。
通过生成范围为0的float值,可以更容易地生成指定范围内的值。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)) }编辑我看到你已经解决了这个问题。我认为我发布的解决方案可能仍然适用于较小的范围(随机生成器不能很快产生足够的匹配值)。
发布于 2012-03-21 19:51:23
问题是参数是错误的。Tomas的建议很好,并且有一些辅助函数来实现它。
// Another id function
let fd (d:double) = d
// Check that it is in bounds
let mn=1.0
let mx=5.0
let fdcheck d = (fd d <= mx) && (fd d >= mn)
// Run the check with the numbers generated within the bounds
Check.Quick (Prop.forAll (Arb.fromGen (Gen.map (fun x->
match x with
| _ when Double.IsNaN x -> (mn+mx)/2.0
| _ when x> 1e+17 ->mx
| _ when x< -1e17 ->mn
| _ -> mn + (mx-mn)*(sin x+1.0)/2.0
) Arb.generate<double>
)
) fdcheck
)这里我有一个函数,如果参数生成正确,它将通过测试。我不确定Tomas关于整数的想法是否有效,因为我认为会生成许多小整数,因此doubles并不会太多地探索这个领域--但也许某个了解FSCheck的人可能会给我们一些启发。
发布于 2016-09-14 20:28:48
以这种方式重写@b1g3ar5中的示例
let mapRangeNormal (min : float<_>, max : float<_>) x =
match x with
| _ when Double.IsNaN x -> (min + max) / 2.0
| _ when Double.IsPositiveInfinity x -> max
| _ when Double.IsNegativeInfinity x -> min
| _ -> min + (max - min) * (sin x + 1.0) / 2.0
let mapRangeUniform (min : float<_>, max : float<_>) x =
match x with
| _ when Double.IsNaN x -> (min + max) / 2.0
| _ when Double.IsPositiveInfinity x -> max
| _ when Double.IsNegativeInfinity x -> min
| _ when x < 0.0 ->
let newRange = max - min
min - x * (newRange / Double.MaxValue) - newRange / 2.0
| _ -> let newRange = max - min
min + x * (newRange / Double.MaxValue) + newRange / 2.0https://stackoverflow.com/questions/9790108
复制相似问题