응용프로그램에서는 흔히 srand(time) 즉 랜덤함수 api 를 써서 랜덤값을 만든다
이것은 rand() 함수에 시간값 (jiffies) 를 시드값으로 넣어서 나온값이다
단점이 있다
jiffies 시간값은 10ms 또는 4ms 에 한번씩 변경된다
즉 그 시간안에 rand() 함수를 실행하면 같은값이 나온다
또한 기본적은 rand() 의 코드는 다양한 난수를 만든다기엔 부족함이 있다
난수분포도가 치우쳐져 있기 때문이다
이것은 rand() 함수가 선형합동법을 쓰는데 선형합동법의 한계이기 때문이다
그리고 메르센 트위스터 기법이 있는데 rand()에 적용된 선형합동법보다 난수분포도가 높고 빠르다고 인정받은 표준이다
개발자들은 rand() 대신 mt_rand () 를 이용하면 된다
그리고 XOR 시프트가 있는데 XOR 과 시프트 연산으로 숫자를 지지고 볶아서 매번 불규칙한 난수로 만들어 내는 거다
시드값이 1만 증가했을 뿐인데 매번 불규칙한 엉뚱한 난수가 나온다
이를 개량시킨 알고리즘들이 많이 나와서 외국에서 좋다는 알고리즘을 가져와서 나름대로 존나게 개조해봤다
난수분포도를 보니 성능은 매우 만족스러웠다
xor shift 의 라이브러리 정식지원은 없는것 같지만 코드가 매우 간단하고 널리 퍼져있으니
함수로 만들어서 난수가 필요할때 가져다 쓰는것도 좋을것 같다
해당 댓글은 삭제되었습니다.
대부분 분야는 관련이 없겠지만 난수 분포도와 관련이 있는 분야에서는 성능이 떨어지겠죠
예를 들면 난수로 값을 수억개 만들고 그것을 해시테이블로 DB로 관리하는 시스템이 있다고 할때, 난수분포도가 고르지 않으면 해시테이블에 고르게 분포되지 않으므로 해시테이블 전체를 제대로 활용 못하고 일부에 데이타들이 몰려있을수 있습니다
그 경우 DB의 서칭, 자료 추가삭제에 더 시간이 걸리겠죠
님 머하는사람임? 자주 관음했는데 고수인거같음
걍 개발자(오타쿠)이고 주 분야는 시스템 프로그래밍임
긍데 xor이랑 시프트를 얼마나 하는지는 어케 정하는거임??생성시마다 그 횟수가 바껴야되는거아닌가
https://en.wikipedia.org/wiki/Xorshift
이게 관련 설명된 영문위키인데 대략 개념을 설명하자면
4bytes 변수라 가정할때 seed 값이 1만 증가해도 그 1의 1,2,3,4 번째 bytes 에 모두 영향을 주는 방식으로 서로 지지고 볶는거임. 그래서 xor 과 shift 하는 알고리즘은 고정되어 있지만 seed 숫자가 1만 변한것만으로도 완전히 다른값, 그리고 1억개를 테스트해도 매번 다른 값이 나오는게 이 알고리즘 의 목적임
즉 rand() 함수처럼 time 값을 넣을필요도 없고 적당한 값만 넣고 그 시드값을 1씩 증가시키는 것만으로 난수가 생성됨
ㅇㅎ
https://en.wikipedia.org/wiki/ACORN_(PRNG)
이건어떰?
죄송 뭔지 잘 모르겠어요;; 아콘소프트웨어?
http://acorn.wikramaratna.org/concept.html
이것도 랜덤 알고리즘인디 [0, 1)
acorn prng로 한번 봐보셈 ㅎㅎ
아하 살펴보고 이해했습니다. 좋은자료 감사해요 살펴볼게요
좀 개소리가 섞여있는데. srand(time) 이건 seed값을 시간값으로 하겠다는거다. 일반적인 난수(의사난수,슈도랜덤)는 기본적으로 "난수표"에서 읽어오는건데, 이 난수표를 정말 표로 만들거나 수식으로 계산하거나 뭘 하든 간에, "시작값" 자체가 랜덤이 되어야 랜덤이 가능한거다. 표가 "1,2,3,4,5"라고 되어 있다면 이걸 어디서부터 시작할지 어떻게 정하지? 그걸 "시간값"에서 읽어서 시작점을 지정해준다는거다. 시간값이 난수를 만드는게 아님.
난수 알고리즘을 사용한다면 seed 값은 time 이 아니어도 쓸수 있는 방법이 있습니다. 바로 임의의 변수를 정한다음 그 변수의 값을 계속 1씩 증가시키는 거죠. 그러면 4bytes 값이 42억개니까 한바퀴돌때까지 42개의 서로 다른 시드값이 나오고, 그것으로 계속 랜덤한 난수가 만들어지는 것이죠. 그 값은 메모리에 저장해도 되고 파일에 저장해도 됩니다. 시간값을 참고할 필요도 없고 난수표를 참고할 필요도 없어요
앗, 다시 읽어보니까 엉뚱한 답변을 했네요. 음 맞습니다. 그건 rand 의 문제가 아니라 seed 값의 문제입니다. 글에서 설명이 잘못되었네요 ㅎㅎ seed 값이 변하지 않으면 어떤 알고리즘을 써도 똑같은 결과가 나오니까요. 감사합니다
즉, srand(time)를 한번만 하면 되는데 이걸 반복문에 쳐 넣어서 난수가 겹치는게 나오는거. 물론 srand(time) 종류를 지정 안하고 해도 똑같이 나오는거. 시작점이 지정 안되니까 매번 똑같은 위치부터 시작하고 똑같은 난수가 나오는거.
https://stackoverflow.com/a/6668328
이런거구나 ㅎㅎ
음. 제 얘기를 이해하신 분이 없기 때문에 설명드릴게요. jiffies 라는 시간값은 timer interrupt 의 기준입니다. 우리가 응용프로그램에서 타이머를 많이 다루죠? 그 타이머를 다룬다는게 특정함수를 timer interrupt 의 리스트에 추가한다는 개념입니다. 그래서 나온 개념이 HZ (헤르츠) 이고요, 1초에 운영체제에서 타이머 인터럽트가 얼마나 많이 실행되는가
이게 왜 중요하냐면 타이머 인터럽트가 실행될때마다 시간값 (jiffies) 값이 1씩 증가하거든요. 그래서 1jiffies 가 10ms 이거나 4ms 인데 (OS마다 다름) 그 시간이내에 시간값을 계속 읽어들여도 같은 값만 나온다는 거죠. 시간값이 변경되기 전에 2번 읽은 것이니까요. 시간값을 시드로 읽어들이는 것의 한계는 이것을 얘기하는 것입니다
그래서 1ms (밀리초)이내에 시간값을 10번 읽어들인다면 모두 같은 값만 나오기 때문에, 시간값이 아닌 임의의 시드값을 가지고 그 시드값을 계속 증가시키면서 넣고, 그 결과로 난수가 나오는 알고리즘이 더 범용적이고 활용성이 높은 알고리즘이겠죠? 타이트한 임베디드 환경에서도 쓸 수 있으니까요
제 답변을 다시 읽어보니 time에 의한 seed 값의 문제점을 적어놓고 알고리즘의 효용성을 얘기하는 전혀 관련없는 얘기를 해버렸네요. 부끄럽습니다. 어떤 알고리즘이든지 time 을 시드값으로 넣으면 금방 한계가 오죠 rand() 함수만의 문제는 아닙니다
시드 세팅은 GetTickCount() ^ GetCurrendProcessId() 같이 하면 되지 않나
Current