R语言传入rnorm()参数时如何实现函数每次调用生成不同结果
问题根因
你最初的写法两次输出完全一致,是因为R在执行函数调用时,会先计算实参的取值,再传入函数内部。也就是说你写simpleTest(rnorm(2, 0, 1))时,rnorm(2,0,1)在进入函数前就已经运行完,生成了一个固定的长度为2的随机向量,传给形参x的是这个固定值,不是随机数生成规则,所以两次print(x)输出的都是同一个提前算好的结果。
实现方案
两种方案都支持任意次数循环调用(包括你需要的10000次重复),每次调用都会生成新的随机值:
方案1:传入函数本体+参数,内部动态调用
把随机数生成函数本身(不要加括号执行)和它的参数分开传入,在函数内部每次需要取值的时候再实际执行函数生成随机数:
simpleTest <- function(gen_func, gen_params = list(), loop_times = 2) { for (i in seq_len(loop_times)) { current_val <- do.call(gen_func, gen_params) print(current_val) } } # 调用示例:传入rnorm函数本体,参数以列表形式传入,循环10000次 simpleTest( gen_func = rnorm, gen_params = list(n = 2, mean = 0, sd = 1), loop_times = 10000 )
这种写法兼容性最好,除了rnorm之外,其他随机数生成函数比如runif、rpois都可以直接用,不需要改函数逻辑。
方案2:传入表达式,内部延迟求值
如果你想直接把rnorm(2, 0, 1)整体作为参数传入,可以利用R的惰性求值特性,先捕获未执行的表达式,每次需要取值时重新计算:
simpleTest <- function(gen_expr, loop_times = 2) { # 捕获传入的未求值表达式,不要提前计算 expr <- substitute(gen_expr) for (i in seq_len(loop_times)) { current_val <- eval(expr) print(current_val) } } # 调用示例:直接写随机数生成表达式即可 simpleTest(rnorm(2, 0, 1), loop_times = 10000)
注意事项
- 不要在传参时提前执行随机数函数,一旦你在实参位置写了完整的带括号的函数调用(比如
rnorm(2,0,1)直接作为实参传给只接收值的形参),传入的就是固定计算结果,不可能再生成新的随机值。 - 两种方案生成的随机数都符合R的随机数生成规则,每次结果独立,和你直接在全局环境循环调用
rnorm的效果完全一致。
内容的提问来源于stack exchange,提问作者Andrew_2992
相关产品推荐
相关产品推荐

