JavaScript의 Math.random은 얼마나 무작위입니까?


116

6 년 동안 웹 사이트에 난수 생성기 페이지 가있었습니다 . 오랫동안 "난수 생성기"에 대한 Google의 첫 번째 또는 두 번째 결과였으며 토론 포럼 및 블로그에서 수백 건은 아니더라도 수십 건의 콘테스트와 그림을 결정하는 데 사용되었습니다. 웹 로그 및 일반적으로 살펴보십시오).

오늘 누군가 제게 이메일을 보냈는데 제가 생각했던 것만 큼 무작위가 아닐 수도 있습니다. 그녀는 매우 큰 난수 (예 : 1에서 10000000000000000000 사이)를 생성하려고 시도했으며 거의 ​​항상 동일한 자릿수임을 발견했습니다. 실제로 저는 함수를 루프로 감싸서 수천 개의 숫자를 생성 할 수 있었고 매우 큰 숫자의 경우 변동이 약 2 배 정도에 불과했습니다.

왜?

다음은 루핑 버전이므로 직접 사용해 볼 수 있습니다.

http://andrew.hedges.name/experiments/random/randomness.html

여기에는 Mozilla 개발자 네트워크 에서 가져온 간단한 구현 과 더 이상 존재하지 않는 웹 페이지 (Paul Houle의 "Central Randomizer 1.3")를 훑어 본 1997 년의 일부 코드가 모두 포함되어 있습니다. 각 방법의 작동 방식을 보려면 소스를보십시오.

나는 Mersenne Twister 에 대해 여기다른 곳에서 읽었습니다 . 제가 관심있는 것은 JavaScript의 내장 Math.random 함수 의 결과에 더 큰 변화가없는 이유 입니다. 감사!


"sarnath'd"에서와 같이 펀치에
맞거나이

5
제목의 질문에 대한 답을 찾고 있다면 stackoverflow.com/questions/2344312/를
Andrew B.

답변:


182

1에서 100 사이의 숫자가 주어집니다.

  • 9에는 1 자리 (1-9)가 있습니다.
  • 90은 2 자리 숫자 (10-99)입니다.
  • 1은 3 자리 숫자 (100)입니다.

1에서 1000 사이의 숫자가 주어집니다.

  • 9에는 1 자리가 있습니다.
  • 90은 2 자리 숫자입니다.
  • 900은 3 자리 숫자입니다.
  • 1은 4 자리 숫자입니다.

등등.

따라서 일부를 무작위로 선택하면 대부분의 가능한 값이 동일한 자릿수를 갖기 때문에 선택한 숫자의 대다수가 동일한 자릿수를 갖게됩니다.


11
완벽하고 균일하게 의미 임의성에 대한 당신의 생각은 ... 흥미로운, 분배

19
@ R.Pate-난수 생성 은 장기적으로 균등하게 분산되지 않는 한 많이 사용되지 않습니다
annakata

3
다시 읽으세요. @David는 N 개의 난수를 선택한 결과가 아니라 한계 사이에 어떤 종류의 숫자가 있는지 만 설명합니다. 제목이 오해의 소지가 있음을 인정합니다.
nikc.org

3
기록을 위해 나는 이것과 @jwoolard의 답변을 모두 투표했습니다. 예제에서 숫자 분포가 더 많은 자릿수를 가진 숫자로 왜곡되는 이유를 명확하게 보여주기 때문에이 답변을 수락 된 답변으로 선택했습니다.
Andrew Hedges

1
@ 꽤 괜찮 앤드류 - 울타리 - 이것은 명확하게 대답이지만, 감사합니다 :)
jwoolard

56

귀하의 결과는 실제로 예상됩니다. 난수가 1 ~ 10 ^ n 범위에서 균일하게 분포 된 경우 숫자의 약 9/10은 n 자리를, 추가 9/100은 n-1 자리를 가질 것으로 예상합니다.


8
바로 그거죠. 자릿수 분포가 왜곡 될 것으로 예상됩니다. 그러나 자릿수의 로그 분포는 균일해야합니다.
Noldorin

45

다양한 유형의 무작위성이 있습니다. Math.random 은 숫자의 균일 한 분포를 제공합니다.

다른 크기의 차수를 원하면 지수 함수를 사용하여 멱 법칙 분포 를 만드는 것이 좋습니다 .

function random_powerlaw(mini, maxi) {
    return Math.ceil(Math.exp(Math.random()*(Math.log(maxi)-Math.log(mini)))*mini)
}

이 기능은 2 자리 숫자와 3 자리 숫자와 거의 동일한 수의 1 자리 숫자를 제공합니다.

정규 분포 (가우스 분포라고도 함) 와 같은 난수에 대한 다른 분포도 있습니다.


이 알고리즘으로, 나는 넣어 minimum = 1과를 maximum = 10때로는 결과로 (11)를 얻을 것입니다. 당신은 아마 Math.floor대신 사용하려고했을 것 입니다Math.round
Sam Eaton

1
왜 작동합니까? 균일 분포를 지수 분포로 변환합니까?
shinzou 2011

@shinzou 나는에 요청 math.stackexchange 과 답변으로 약간 다른 공식을 얻었다. math.stackexchange에서 수학적으로 파생 된 공식을 반영하도록 코드를 변경했습니다.
Christian

20

나에게 완벽하게 무작위로 보인다! (힌트 : 브라우저에 따라 다릅니다.)

개인적으로 XKCD 에서 훔 쳤지 만 내 구현이 더 좋을 것이라고 생각 합니다.

function random() {
  return 4; // Chosen by a fair dice throw. Guaranteed to be random.
}

19
브라우저에 따라 다르므로 +1, 링크없이 xkcd를 빌리면 -1.

xkcd이기 때문에 필수 여부에 관계없이 어트 리뷰 션됩니다. :)
Arafangion

2
OT : "XKCD"가 이번 주 대학 챌린지 질문에 대한 답이되어 놀랍고 기쁩니다. : D
Matt Sach

2
Bergi : 직접 링크로는 충분하지 않습니까?
Arafangion 2013-06-04

농담이 올바르게 인용되지 않았다는 의미라고 생각합니다 ( "return 4;"대신 "random = 4;")
Eren Tantekin

18

다음 문서에서는 주요 웹 브라우저의 math.random ()이 어떻게 (비) 안전한지 설명합니다. Amid Klein (2008)의 "주요 브라우저의 임시 사용자 추적 및 도메인 간 정보 유출 및 공격" . 일반적인 Java 또는 Windows 내장 PRNG 기능보다 강력하지 않습니다.

반면 2 ^ 19937-1 기간의 SFMT를 구현하려면 각 PRNG 시퀀스에 대해 2496 바이트의 내부 상태가 유지되어야합니다. 어떤 사람들은 이것을 용서할 수없는 비용으로 생각할 수 있습니다.


1
+1 : 언급 된 논문은 원래 질문에 대한 내용을 훨씬 뛰어 넘는 훌륭합니다.
Roland Illig 2011 년

6

10000000000000000000과 같은 숫자를 사용하면 Javascript가 사용하는 데이터 유형의 정확성을 넘어서는 것입니다. 생성 된 모든 숫자는 "00"으로 끝납니다.


1
하지만이 경우 그의 문제는 아닙니다.
Joey

3
@Johannes- 그의 문제 중 하나 입니다 :)
annakata 2009-06-30

IEE754의 배포는 균등하지 않습니다. 아마도 0에서 999까지를 2 씩 증가시켜 표현할 수 있고 충분한 정밀도를 가질 수 있으므로 숫자를 여러 번 선택하면 해당 범위에서 균등 한 분포를 알 수 있습니다. 10 %는 두 자리, 90 %는 세 자리입니다. 하지만 정말 높은 숫자를 기록하기 시작하면 증가는 1을 초과 할 것입니다. 1 조에서 1 조로 1 조에서 1 조로 1 조에서 1 조로 만 단계를 이동할 수 있습니다. 작은 숫자 / 스케일의 경우이 효과는 존재하지 않거나 무시할 수 있습니다. 스케일 효과는 훨씬 더 많은 영향을 미칩니다.
jgmjgm

5

Chaos Game 에서 JS 의사 난수 생성기를 사용해 보았습니다 .

Sierpiński 삼각형 은 꽤 무작위라고 말합니다. 프랙탈


2
다른 브라우저에서 실제로 쉽게 확인할 수 있도록 여기에 삼각형 코드와 jsfiddle / jsbin을 공유해 주시겠습니까?
Fabrício Matté 2013 년

1
좋아요.하지만 코드를 영어로 번역해야하니 며칠 만주세요. 지금은 폴란드어-영어이고 많은 일이 있습니다.
zie1ony

1
@ zie1ony 며칠이 다되었습니다.
trusktr 2013

1
usp :( work, work, work 링크 : kubaplas.vot.pl/green/fractal 첫 번째 매개 변수는 정점의 nr입니다. 두 번째 매개 변수는 선분 의 교차점 (0에서 1)입니다. 실험 만하면됩니다.
zie1ony

4
Link dead-아마도 Github repo일까요?
Mark K Cowan

3

글쎄요, 만약 당신이 1e6까지의 숫자를 생성한다면, 거의 같은 확률로 모든 숫자를 얻을 수 있기를 바랍니다. 이는 또한 한 자릿수가 적은 숫자를 얻을 확률이 10 분의 1 밖에 없다는 것을 의미합니다. 100 분의 1의 확률로 두 자릿수를 줄일 수 있습니다. 다른 RNG를 사용할 때 큰 차이를 볼 수 있을지 의심 스럽습니다. 왜냐하면 로그가 아닌 숫자에 걸쳐 균일 한 분포를 가지기 때문입니다.


0

1에서 N까지 균일하게 분포 된 난수가 아닌 숫자는 동일한 속성을 갖습니다. (어떤 의미에서) 그것은 정밀도의 문제라는 점에 유의하십시오. 0-99 (정수)의 균일 분포는 숫자의 90 %가 두 자리 수를 갖습니다. 0-999999의 균등 분포에는 5 자리 숫자가 905 개 있습니다.

모든 숫자 집합 (너무 제한적이지 않은 일부 조건에서)에는 밀도가 있습니다. 누군가 "무작위"숫자에 대해 논의하고 싶을 때 이러한 숫자의 밀도를 지정해야합니다 (위에서 언급 한대로). 공통 밀도는 균일 한 밀도입니다. 다른 것들이 있습니다 : 지수 밀도, 정규 밀도 등. 난수 생성기를 제안하기 전에 어떤 밀도가 적절한 지 선택해야합니다. 또한 한 밀도에서 나오는 숫자는 종종 다양한 방법으로 다른 밀도로 쉽게 변환 될 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.