Бесконечный случайный поток

У меня возникли проблемы с созданием бесконечного случайного потока чисел от 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

Любые идеи о том, как инициировать случайную функцию каждый раз, когда бесконечный цикл начинается заново? Я перерыл весь интернет, но не нашел способа решить эту проблему.


person Derorrist    schedule 02.07.2013    source источник
comment
Кстати, похоже, вы используете #%require и устаревшую библиотеку mzscheme. Вероятно, будет намного проще, если вы используете #lang racket (у которого есть, например, встроенный random).   -  person Asumu Takikawa    schedule 02.07.2013
comment
Спасибо, что обратили мое внимание   -  person Derorrist    schedule 02.07.2013


Ответы (2)


Как бы то ни было, процедура random вызывается только один раз, потому что вы не вызывали рекурсивно input_stream снова, поэтому все случайные числа в потоке на самом деле являются одним и тем же числом. Вы должны гарантировать, что генератор псевдослучайных чисел вызывается каждый раз, когда новое значение получает cons, например:

(define (random-stream n)
  (cons (random n) (delay (random-stream n))))

Теперь этот поток будет содержать случайные числа в диапазоне 0-9:

(define input_stream (random-stream 10))

Примечание. Я определил n как параметр, чтобы сделать сгенерированный поток параметризуемым, он будет работать так же хорошо с фиксированным значением:

(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

Или вообще для генерации списка из m случайных элементов от 0 (включительно) до n (не включая):

(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
person Óscar López    schedule 02.07.2013
comment
Спасибо вам за быстрый ответ. - person Derorrist; 02.07.2013
comment
В любом случае я могу напечатать первые несколько чисел? В исходном коде я вижу первое число с (input_stream), но в вашем коде я получаю сообщение об ошибке, что это не процедура... Я уверен, что это очевидные вопросы, извините за это, я совсем новичок, когда это приходит к схеме. - person Derorrist; 02.07.2013
comment
Смотрите мой обновленный ответ. Обратите внимание, что это реализация потоков с нуля, в Racket для этого есть встроенные примитивы, например stream-cons - person Óscar López; 02.07.2013
comment
Большой! спасибо за помощь. Надеюсь, я смогу реализовать бесконечный поток с помощью кодировщика. - person Derorrist; 02.07.2013

Я не уверен, насколько целесообразно создавать случайный поток, поскольку простой повторный вызов (random n) приведет к тому же эффекту.

Но хороший способ создавать потоки — использовать stream-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))
person uselpa    schedule 02.07.2013