- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 재능이의 돈버는 일기
- StresslessLife
- K_JIN2SM
- 소소한 일상
- My Life Style & Memory a Box
- Blog's generation
- 공감 스토리
- 취객의 프로그래밍 연구실
- Love Me
- Dream Archive
- 세상에 발자취를 남기다 by kongmingu
- hanglesoul
- 카마의 IT 초행길
- 느리게.
- 미친듯이 즐겨보자..
- Joo studio
- Gonna be insane
- 악 다 날아갔어!! 갇대밋! 왓더...
- xopowo05
- 맑은공기희망운동
- 엔지니어 독립운동
- 혁준 블로그
- Simple in Complex with Simple
- 무의식이 의식을 지배한다
드럼치는 프로그래머
[C/C++] rand() % M 사용하지 말라!!! 본문
사이트 돌아다니다가 rand() 관련 글이 있길래 영어공부 하는 셈치고 대충
번역해보았습니다..가다듬는 작업을 안했으므로 신뢰성 -100% 그냥 심심해서
해본거니까 -.-;....
원문은 아래 사이트에 있으니 원문보고 싶으시면 가보시길..
원문 :http://members.cox.net/srice1/random/crandom.html
=============================================================================
ANSI C에서는 rand()는 0과 RAND_MAX 범위 안의 정수를 무작위로 발생 시키는데
RAND_MAX값은 stdlib.h에 정의되어 있고 일반적으로 최소 32767 이상이다.
주목 할 것은 32767 이라는 수가 큰 수가 아니라는 점이다.
만약 RAND_MAX가 32767 이라면 시퀀스가 시작되어 난수성을 상실할 때까지 20000개의 난수 정수를 얻을 수 있을 것이다.
RAND_MAX는 더 커져야 한다.
당신을 위해서라도 RAND_MAX 값을 확인해보자.
경험상 난수성을 상실 할 때까지 RAND_MAX의 2/3 정도의 숫자만 발생 할 수 있을 것이다.
안전을 위해서 나는 RAND_MAX의 1 / 10 보다 작은 난수 값을 만들 것을 추천한다.
만약 RAND_MAX의 1 / 10 이상보다 더 큰 수를 필요로 한다면 SOURCE CODE AND DISCUSSION OF NEWER & BETTER RANDOM NUMBER GENERATORS 에 있는 새롭고 개선 된 방법을 찾도록 해라
RAND_MAX 값을 확인하는 방법
#include <stdio.h>
#include <stdlib.h>
main()
{
printf("RAND_MAX = %u\n", RAND_MAX);
}
C와 C++에서 rand() 함수의 사용 예
#include <stdio.h>
#include <stdlib.h>
main()
{
/* 변수 선언 */
int seed; /* 난수생성을 위하여
초기값이 같은 경우 발생되서 나오는 난수는 동일하기 때문에
다음번 난수 생성시에 다른 숫자를 발생 시키고 싶다면
초기값을 다르게 설정해야 한다.
*/
double r; /* 범위 [0, 1) 사이의 난수 값 */
long int M; /* 사용자가 설정한 상위 제한범위 */
double x; /* 범위 [0, M) 사이의 난수 값 */
int y; /* 범위 [0, M) 사이의 난수 정수..
만약 M이 정수라면 범위는 [0, M - 1) */
int z; /* 범위 [1, M + 1) 사이의 난수 정수..
만약 M이 정수라면 범위는 [1, M] */
int count; /* 이 예제에서 얼마나 많은 난수를 발생 시켰는지
필요할 때 사용할 변수 */
/* 코드 시작 */
seed = 10000; /* 초기값 설정 */
srand(seed); /* 난수 발생기 초기화 */
M = 1000; /* 제한범위를 설정 (M은 RAND_MAX보다 작아야 한다) */
for(count=1; count<=20; ++count)
{
r = ( (double)rand() / ((double)(RAND_MAX)+(double)(1)) );
/* r은 범위 [0, 1)..0포함 1제외 의 난수 부동소수점
정수로 나누는 것을 피하기 위해 rand() 와
RAND_MAX + 1을 부동소수점으로 변환하였다. */
x = (r * M);
/* x는 범위 [0, M) 사이의 난수 부동소수점...0포함 M미만 */
y = (int) x;
/* y는 범위 [0, M) 사이의 난수 정수값...0포함 M미만
즉 M이 정수라면 범위는 [0, M - 1] */
z = y + 1;
/* z는 범위 [1, M + 1)의 난수 정수값...1포함 M + 1 미만
즉 M이 정수라면 범위는 [1, M] */
printf("random number %3d %5f %5f %5d %5d\n",count,r,x,y,z);
}
}
M의 값에 따라서 범위를 확장 또는 축소 시킬 수 있다.
범위를 올리거나 또는 내리는 것에 따라서 나오는 숫자들의 고정값도 더해지거나 빼질것이다.
주의: 절대 사용하지 말라!
y = rand() % M;
rand()의 하위비트에 살펴보자.
선형적인 난수 생성기는 rand()가 자주 불리면 상위 바이트에 비해서 하위 바이트가 난수성을 잃어 간다.
사실 최하위비트는 0과 1에서만 순환한다.
그리하여 rand()는 짝수와 홀수로 순환한다 (직접 해보라)
주의 할 점은 rand()는 linear congruential random number generators 가 아니라는 것이다.
이러한 문제가 없다면 꽤 사용할만한 것이다.
우리는 r, x,y, z를 생성할 수 있는 방정식을 조합 할 수 있다.
r = [0,1) = {r: 0 <= r < 1} 실수
x = [0,M) = {x: 0 <= x < M} 실수
y = [0,M) = {y: 0 <= y < M} 정수
z = [1,M] = {z: 1 <= z <= M} 정수
주의 할 점은 rand() 와 RAND_MAX + 1을 부동소수점형태(double)로 캐스팅을 한 후에 나눠야 한다.
RAND_MAX가 아키텍처에서 표현 할 수 있는 최대 양수정수 값일 가능성이있다.
그래서 (RAND_MAX) + 1이 오버플로우 또는 아키텍처에서 표현 할 수 있는 가장 큰 음수정수 값으로 변환 될 수 있기 때문에 RAND_MAX와 1을 더하기전에 double 형태로 컨버팅을 한다.
M이 정수라면 y의 결과는 0과 M - 1 포함
M이 정수라면 z의 결과는 1과 M – 1 포함
주의 할 점은 계산시의 순서이다.
우리는 [rand() * M] 을 계산 시에 우리 컴퓨터가 표현 할 수 있는 최대 정수값을 넘어서는 (오버플로우)를 원하지 않을 것이다.
그래서 x,y,z는 이 형태로도 계산 할 수 있다.
여기서 [(double)(RAND_MAX) + (double)1] / (double)M 과 rand()로 나눗셈을 하여 결과를 계산한다.
마찬가지로 M이 정수라면 y의 결과는 0과 M – 1 포함하고
z의결과도 1과 M 포함이다.
Dave Beleznay는 M이 RAND_MAX보다 클수록 더 큰차이의 결과를
얻을 수 있다고 한다.
또한 M이 아주 큰 값일 지라도 RAND_MAX / M이 0에
접근하면 언더플로우가 발생 할 수 있는 문제가 있다.(알아서 예외 처리 하라는걸지도..)
다시한번 강조하자면 : 절대 쓰지 말라!!!
y = rand() % M;
[주의 : 어떤 C 언어의구현에서 저 공식의 사용이 필요 하지 않을 수 있다.
당신이 사용하는 C언어의 구현에서는 완전히 다른 방식의
난수 발생 수도 코드를 사용 할 수도 있기 때문이다
[출처] rand() % M 사용하지 말라!!!|작성자 사랑한톨
'★─Programing > ☆─C | C++' 카테고리의 다른 글
[C/C++] #include <iostream>(신버전) VS #include <iostream.h>(구버전) (0) | 2009.09.29 |
---|---|
[C/C++] 닷넷2003에는 iostream.h가 없다!? (0) | 2009.09.29 |
[C/C++] rand()함수.. 범위가 작구나 -> n * rand ( ) / RAND_MAX + 1 (0) | 2009.02.03 |
[C/C++] 랜덤함수의 표현범위 늘리는 방법 ( rand(), srand(), RAND_MAX ) (2) | 2009.02.03 |
[C/C++] Sleep함수 쓰는방법 ( 1초 대기 ) (1) | 2009.02.03 |