我正在尝试使用F#生成随机三元组列表 - >两个随机数及其总和:
let foo minNum maxNum =
let rnd = System.Random()
let first = rnd.Next(minNum, maxNum)
let second = rnd.Next(minNum, maxNum)
let third = first + second
first, second, third
Run Code Online (Sandbox Code Playgroud)
可以像这样调用并运行良好(总是给出一个新的随机数)(当使用F#interactive时)
foo 0 50
Run Code Online (Sandbox Code Playgroud)
当试图生成这样的随机三元组列表时
List.init 100 (fun index -> foo 0 50)
Run Code Online (Sandbox Code Playgroud)
我希望这是一个包含100个随机三元组的列表,但相反它们都具有相同的值.我可以看到该函数不依赖于索引,因此不需要重新计算,但我不知道如何解决它(我尝试将索引作为未使用的虚拟变量引入,也尝试将索引作为一个引入随机种子,但没有帮助)
sep*_*p2k 14
您假设您的代码不能像您希望的那样工作的原因是编译器错误地应用某种公共子表达式消除,这导致foo 0 50仅被评估一次.不是这种情况.编译器非常清楚函数可能是不纯的,并且不会执行会破坏不纯的代码的优化(除非可以证明优化的特定代码是纯的).因此,您不必担心让编译器认为您正在使用该参数.
问题不仅仅是foo 0 50被调用一次 - 它确实被称为100次,就像你想要的那样.问题是它在调用100次时返回相同的值.
但是,当你手动测试时,它为什么会返回不同的值呢?
因为每次调用时都会创建一个新的Random对象foo.由于您没有为该随机对象提供种子值,因此将使用当前系统时间播种.因此,如果您多次调用该函数并在其间传递一段时间,则每次都会返回不同的值.但是,如果您在如此短的时间内调用它100次,系统时间不会在两者之间发生变化,那么您将获得100次相同的值.
因此,您的问题的解决方案是重用相同的随机对象,而不是每次foo调用时创建一个新的随机对象.
alu*_*lun 12
试试这个.它将重用相同的随机对象,而无需在主范围内保留一个随机对象:
let foo =
let rnd = System.Random()
fun minNum maxNum ->
let first = rnd.Next(minNum, maxNum)
let second = rnd.Next(minNum, maxNum)
let third = first + second
first, second, third
Run Code Online (Sandbox Code Playgroud)
另请注意,Next不是线程安全的,因此如果您打算从多个线程使用foo,则需要向Next添加一些锁定.
| 归档时间: |
|
| 查看次数: |
3155 次 |
| 最近记录: |