我在创建从0到9的无限随机数字流时遇到了一些问题。这就是我现在的处境:
(#%require (only mzscheme random))
(define (input_stream) (cons (random 9) (delay input_stream)))
唯一的问题是,(random 9)
似乎只启动过一次。流确实是随机的,但流的值保持不变。
我得到7, 7, 7, 7, 7
或3, 3, 3, 3, 3
关于每次无休止循环开始时如何启动随机函数,有什么想法吗?我在网上到处找,但找不到解决这个问题的方法。
实际上,random
过程只调用一次,因为您没有再次递归调用input_stream
,这就是为什么流中的所有随机数实际上都是相同的数字。您必须保证每次新值被cons
'ed时都会调用伪随机数生成器,例如:
(define (random-stream n)
(cons (random n) (delay (random-stream n))))
现在这个流将包含0-9范围内的随机数:
(define input_stream (random-stream 10))
注意:我将n
定义为一个参数jut,以使生成的流可参数化,它在固定值下也能正常工作:
(define (random-stream)
(cons (random 10) (delay (random-stream))))
(define input_stream (random-stream))
例如,要访问前三个元素:
(car input_stream)
=> 9 ; random number between 0-9
(car (force (cdr input_stream)))
=> 7 ; random number between 0-9
(car (force (cdr (force (cdr input_stream)))))
=> 8 ; random number between 0-9
或者通常,用于生成从0(包括0)到n
(不包括)的m
随机元素的列表:
(define (stream-take s m)
(if (zero? m)
'()
(cons (car s)
(stream-take (force (cdr s)) (sub1 m)))))
(stream-take (random-stream 10) 20) ; n=10, m=20
=> '(3 3 3 7 0 7 3 2 3 7 6 0 6 4 1 4 6 1 6 9) ; 20 random numbers between 0-9
我不确定创建一个随机流有多大意义,因为简单地重复调用(random n)就能达到同样的效果。
但创建流的一个好方法是使用流cons:
#lang racket
;;; infinite stream of random numbers
(define (random-stream n)
(stream-cons
(random n)
(random-stream n)))
如何消费流很重要,因为如果你做错了,每次都可能得到第一个数字:
(define S (random-stream 10))
;;; right
(for/list ((i (range 5)))
(stream-ref S i))
=> '(7 1 4 8 4)
;;; right
; primitive to take the first n elements of a stream
(define (stream-take s n)
(for/list ((e s) (i (in-range n)))
e))
(stream-take S 20)
=> '(7 1 4 8 4 3 9 8 6 8 4 8 1 1 1 7 0 3 9 4)
;;; wrong
(for/list ((i (range 5)))
(stream-take S 1))
=> '((7) (7) (7) (7) (7))