Random 클래스
Random 클래스
Random은 Ruby의 의사 난수 생성기(PRNG, Pseudo-Random Number Generator) 인터페이스를 제공해요. PRNG는 진짜 무작위에 가까운 결정적(deterministic) 비트 수열을 만들어 내는데, 이 수열을 정수·부동소수점·바이너리 문자열로 표현할 수 있어요.
출처: Ruby 3.3 API
본문
생성기(제너레이터)는 Random.srand로 시스템이 만들거나 사용자가 준 시드(seed) 값으로 초기화할 수 있어요. 클래스 메서드 Random.rand는 Kernel.rand의 기본 기능에 부동소수점 처리를 더 잘 보강한 거예요. 둘 다 Ruby 시스템 PRNG의 인터페이스예요.
Random.new는 Ruby 시스템 PRNG와 독립적인 상태를 가진 새 PRNG를 만들어요. 그래서 서로 다른 시드나 수열 위치를 가진 여러 생성기를 동시에 만들 수 있어요. Random 객체는 마샬(marshal)할 수 있어서, 수열을 저장했다가 이어서 재개할 수도 있어요.
PRNG는 현재 변형된 Mersenne Twister로 구현되어 있고, 주기(period)는 2**19937-1이에요. 이 알고리즘은 암호화용이 아니므로, 보안이 필요할 때는 이 PRNG 대신 SecureRandom을 써야 해요.
또한 다양한 형태의 난수 데이터를 생성하는 편의 메서드를 추가해 주는 Random::Formatter 모듈도 참고하세요.
Public Class Methods
bytes(size) → string
무작위 바이너리 문자열을 반환해요. 인자 size는 반환 문자열의 길이를 지정해요.
new(seed = Random.new_seed) → prng
seed로 초기 상태를 설정해 새 PRNG를 만들어요. seed를 생략하면 Random.new_seed로 초기화해요. 시드 값 사용에 대한 자세한 내용은 Random.srand를 참고하세요.
new_seed → integer
임의의 시드 값을 반환해요. Random.new에 시드 인자를 주지 않을 때 사용돼요.
Random.new_seed #=> 115032730400174366788466674494640623225
rand → float, rand(max) → number, rand(range) → number
Ruby 시스템 PRNG를 사용해 난수를 반환해요. Random#rand도 함께 참고하세요.
seed → integer
Ruby 시스템 PRNG를 초기화하는 데 사용된 시드 값을 반환해요. 나중에 이 값으로 다른 생성기를 초기화하면 같은 상태가 되어 같은 수열을 만들어 낼 수 있어요.
Random.seed #=> 1234
prng1 = Random.new(Random.seed)
prng1.seed #=> 1234
prng1.rand(100) #=> 47
Random.seed #=> 1234
Random.rand(100) #=> 47
srand(number = Random.new_seed) → old_seed
시스템 의사 난수 생성기를 number로 시드(seed)해요. 이전 시드 값을 반환해요. number를 생략하면 운영체제가 제공하는 엔트로피 소스(Unix의 /dev/urandom이나 Windows의 RSA 크립토 제공자)에 시간·프로세스 ID·수열 번호를 결합해서 시드해요.
srand는 프로그램 실행 간 반복 가능한 난수 수열을 보장하는 데 쓸 수 있어요. 시드를 알려진 값으로 설정하면 테스트 중에 프로그램을 결정적으로 만들 수 있죠.
srand 1234 # => 268519324636777531569100071560086917274
[ rand, rand ] # => [0.1915194503788923, 0.6221087710398319]
[ rand(10), rand(1000) ] # => [4, 664]
srand 1234 # => 1234
[ rand, rand ] # => [0.1915194503788923, 0.6221087710398319]
urandom(size) → string
플랫폼이 제공하는 기능을 사용해 문자열을 반환해요. 반환값은 바이너리 형태의 암호학적으로 안전한(예상되는) 난수예요. 플랫폼 기능이 결과를 준비하지 못하면 RuntimeError를 발생시켜요.
2017년 Linux random(7) 매뉴얼은 "오늘날 어떤 암호화 프리미티브도 256비트 이상의 보안을 약속할 수 없다"고 적고 있어요. 그래서 이 메서드에 size > 32를 넘기는 건 의문이 있을 수 있어요.
Random.urandom(8) #=> "\x78\x41\xBA\xAF\x7D\xEA\xD8\xEA"
Public Instance Methods
prng1 == prng2 → true or false
두 생성기의 내부 상태가 같으면 true, 그렇지 않으면 false를 반환해요. 동등한 생성기는 같은 의사 난수 수열을 반환해요. 일반적으로 두 생성기는 같은 시드로 초기화되었을 때만 같은 상태를 가져요:
Random.new == Random.new # => false
Random.new(1234) == Random.new(1234) # => true
그리고 같은 호출 이력을 가질 때만 같아요.
prng1 = Random.new(1234)
prng2 = Random.new(1234)
prng1 == prng2 # => true
prng1.rand # => 0.1915194503788923
prng1 == prng2 # => false
prng2.rand # => 0.1915194503788923
prng1 == prng2 # => true
bytes(size) → string
size 바이트만큼의 무작위 바이너리 문자열을 반환해요.
random_string = Random.new.bytes(10) # => "\xD7:R\xAB?\x83\xCE\xFAkO"
random_string.size # => 10
rand → float, rand(max) → number, rand(range) → number
max가 Integer면 rand는 0 이상 max 미만의 무작위 정수를 반환해요. Kernel.rand와 달리, max가 음수 정수이거나 0이면 rand는 ArgumentError를 발생시켜요.
prng = Random.new
prng.rand(100) # => 42
max가 Float면 rand는 0.0 이상 max 미만(0.0 포함, max 제외)의 무작위 부동소수점을 반환해요.
prng.rand(1.5) # => 1.4600282860034115
range가 Range면 rand는 range.member?(number) == true인 무작위 숫자를 반환해요.
prng.rand(5..9) # => one of [5, 6, 7, 8, 9]
prng.rand(5...9) # => one of [5, 6, 7, 8]
prng.rand(5.0..9.0) # => between 5.0 and 9.0, including 9.0
prng.rand(5.0...9.0) # => between 5.0 and 9.0, excluding 9.0
범위의 시작과 끝 값은 모두 빼기(-)와 더하기(+) 메서드에 응답해야 하고, 그렇지 않으면 rand는 ArgumentError를 발생시켜요.
seed → integer
생성기를 초기화할 때 사용된 시드 값을 반환해요. 나중에 이 값으로 다른 생성기를 초기화하면 같은 상태가 되어 같은 수열을 만들어 낼 수 있어요.
prng1 = Random.new(1234)
prng1.seed #=> 1234
prng1.rand(100) #=> 47
prng2 = Random.new(prng1.seed)
prng2.rand(100) #=> 47