programing

랜덤 (Java 7)의 181783497276652981 및 8682522807148012는 무엇입니까?

newsource 2022. 10. 26. 21:07

랜덤 (Java 7)의 181783497276652981 및 8682522807148012는 무엇입니까?

★★★★★★★★★★★★★★★★★★★★.181783497276652981 ★★★★★★★★★★★★★★★★★」8682522807148012.Random.java

Java SE JDK 1.7의 관련 소스 코드를 다음에 나타냅니다.

/**
 * Creates a new random number generator. This constructor sets
 * the seed of the random number generator to a value very likely
 * to be distinct from any other invocation of this constructor.
 */
public Random() {
    this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
    // L'Ecuyer, "Tables of Linear Congruential Generators of
    // Different Sizes and Good Lattice Structure", 1999
    for (;;) {
        long current = seedUniquifier.get();
        long next = current * 181783497276652981L;
        if (seedUniquifier.compareAndSet(current, next))
            return next;
    }
}

private static final AtomicLong seedUniquifier
    = new AtomicLong(8682522807148012L);

「」를 기동합니다.new Random()가 없는 경우 " uniquiifier"를을 "Seed uniquiifier 에는 "Seed uniquiifier"를 지정합니다.System.nanoTime()그,를 사용합니다.181783497276652981에 구분자를 new Random()출됩니니다다

★★★★181783497276652981L ★★★★★★★★★★★★★★★★★」8682522807148012L상수에 배치되지 않지만 다른 곳에는 나타나지 않습니다.

처음에 그 코멘트는 나에게 쉬운 단서를 준다.그 기사를 인터넷에서 검색하면 실제 기사가 나옵니다. 8682522807148012에는 실리지 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」181783497276652981 다른됩니다.1181783497276652981, 「」)181783497276652981 a 1프리펜드롭습니다.

은 '아주 좋다'고 하고 있다.1181783497276652981는 선형 합동 생성기에 대해 양호한 "변수"를 산출하는 숫자입니다.자바?181783497276652981은은점 이이?

왜 ★★★★★★★★★★★★★★★★★★★?8682522807148012선하?????

어느 쪽이든 온라인으로 검색해도 설명이 표시되지 않고, 드롭된 것을 알 수 있는 페이지만 표시됩니다.1181783497276652981.

이 두 숫자만큼 다른 숫자도 선택될 수 있었을까요?왜 그런가요? 혹은 왜 그렇지 않은가요?

  1. 이 번호가 단순히 Java에 잘못 복사된 건가요?

    네, 오타인 것 같아요.

  2. 181783497276652981이 허용 가능한 장점이 있습니까?

    이는 논문에 제시된 평가 알고리즘을 사용하여 결정할 수 있습니다.하지만 "오리지널" 번호의 장점은 아마도 더 높을 것이다.

  3. 그리고 왜 8682522807148012가 선택되었습니까?

    무작위로 보이는군코드 작성 시 System.nanoTime()의 결과일 수 있습니다.

  4. 이 두 숫자만큼 다른 숫자도 선택될 수 있었을까요?

    모든 숫자가 똑같이 "좋은" 것은 아닙니다.그래서 안 돼.

시드 전략

JRE의 버전 및 구현에 따라 디폴트시딩 스키마에는 차이가 있습니다.

public Random() { this(System.currentTimeMillis()); }
public Random() { this(++seedUniquifier + System.nanoTime()); }
public Random() { this(seedUniquifier() ^ System.nanoTime()); }

여러 RNG를 연속해서 작성할 경우 첫 번째 RNG는 허용되지 않습니다.생성 시간이 같은 밀리초 범위에 있으면 완전히 동일한 시퀀스를 얻을 수 있습니다.(같은 시드 => 같은 시퀀스)

두 번째는 스레드 세이프가 아닙니다.여러 스레드가 동시에 초기화할 때 동일한 RNG를 얻을 수 있습니다.또한 후속 초기화의 시드는 상관관계가 있는 경향이 있습니다.시스템의 실제 타이머 분해능에 따라 시드 시퀀스가 선형적으로 증가할 수 있습니다(n, n+1, n+2, ...).'랜덤 시드(Random seeds)는 얼마나 다를 필요가 있는가?'와 참조된 논문 '의사난수 발생기 초기화 시 공통 결함'에서 설명한 바와 같이 상관된 시드는 여러 RNG의 실제 시퀀스 간에 상관관계를 생성할 수 있다.

세 번째 접근법은 쓰레드와 후속 초기화에 이르기까지 랜덤하게 분산되어 상관관계가 없는 시드를 생성합니다.현재 Java 문서는 다음과 같습니다.

이 생성자는 랜덤 번호 생성기의 시드를 이 생성자의 다른 호출과 다를 수 있는 값으로 설정합니다.

"실제 스레드"와 "상관없는"으로 확장할 수 있습니다.

시드 시퀀스 품질

그러나 시드 시퀀스의 무작위성은 기초 RNG만큼 우수합니다.이 Java 구현에서 시드 시퀀스에 사용되는 RNG는 c=0 및 m=2^64의 곱셈 선형 합동 생성기(MLCG)를 사용합니다(계수 2^64는 64비트 긴 정수의 오버플로에 의해 암묵적으로 주어집니다). 왜냐하면 0c와 2-계수의 거듭제곱은 "품질(사이클 길이, 제한됨)"입니다.이 문서에서 설명한 바와 같이 전체 사이클 길이 외에 모든 비트는 고유한 사이클 길이를 가지며, 이는 중요하지 않은 비트에 대해 기하급수적으로 감소합니다.따라서 낮은 비트의 반복 패턴은 작습니다(실제 RNG에서는 48비트로 잘라내기 전에 seedUniquifier()의 결과는 비트 반전되어야 합니다).

하지만 빨라요!또한 불필요한 비교 및 설정 루프를 피하기 위해 루프 본체가 빠를 필요가 있습니다.이것은 아마도 이 특정 MLCG의 사용법을 설명하는데, 추가나 xoring을 사용하지 않고, 곱셈을 1개만 합니다.

그리고 상기 논문은 c=0 및 m=2^64에 대한 양호한 "선량" 목록을 1181783497276652981로 제시한다.

모두: A for effort @ JRE-developers) 그러나 오타가 있다(그러나 누가 평가하지 않는 한, 실제로 리드 1이 시딩 RNG를 개선할 가능성이 있다).

그러나 일부 승수는 확실히 더 나쁩니다. "1"은 연속적인 시퀀스로 이어집니다."2"는 단일 비트 이동 시퀀스로 이어집니다(상관된 시퀀스 표시).

RNG에 대한 시퀀스 간 상관관계는 실제로 (몬테 카를로) 시뮬레이션과 관련이 있으며, 여기에서 여러 개의 랜덤 시퀀스가 인스턴스화되고 병렬화된다.따라서 "독립적인" 시뮬레이션 실행을 얻으려면 좋은 시드 전략이 필요합니다.따라서 C++11 규격에서는 상관없는 시드 생성을 위한 시드 시퀀스의 개념을 도입하고 있습니다.

난수 생성기에 사용되는 방정식은 다음과 같습니다.

LCGEquation

여기서 X(n+1)는 다음 수, a는 승수, X(n)는 현재 수, c는 증분, m은 계수입니다.

더 보면요.Random, a,c및a, c, m, m으로 정의되어

private static final long multiplier = 0x5DEECE66DL;   //= 25214903917 -- 'a'
private static final long addend = 0xBL;               //= 11          -- 'c'
private static final long mask = (1L << 48) - 1;       //= 2 ^ 48 - 1  -- 'm'

protected int next(int bits)되었을 때 입니다.

nextseed = (oldseed * multiplier + addend) & mask;
//X(n+1) =  (X(n)   *      a     +    c  ) mod m

은, 「」의 방식이 「」를 있는 것을 의미합니다.seedUniquifier() X X(의 첫 는 X(n)를 하고 있습니다.또는 첫 번째 경우 초기화 시 X(0)를 취득하고 있습니다.8682522807148012 * 181783497276652981 다음, 이 더System.nanoTime()이이은( X(0) =8682522807148012a= , a =181783497276652981, m= 및 c=단, 의긴은 m = 2 ^64 c = 0이 됩니다.mod m은 mod m이 됩니다.

eq2

=의 가치에 대한 논문을 보면1181783497276652981는 m =c이며, 은 m = 2 ^64, c = 0 입니다.을 사용하다8682522807148012, X(0)의 입니다.Random여기 보시는 것처럼.그러나 이 선택된 숫자들의 장점은 여전히 유효할 수 있지만 토마스 B가 언급한 것처럼 아마도 신문에 나온 숫자만큼 "좋은" 것은 아닐 것이다.

편집 - 그 후 아래 원래의 생각이 명확해졌기 때문에 무시해도 되지만 참고용으로 남겨둡니다.

이 결론은 다음과 같습니다.

  1. 이 문서에 대한 참조는 값 자체가 아니라 a, c, m의 값이 다르기 때문에 값을 얻기 위해 사용되는 방법에 대한 것입니다.

  2. 값이 선두 1과 동일하지 않고 코멘트가 잘못되어 있는 것은 우연의 일치에 지나지 않습니다(하지만, 여전히 이 사실을 믿기 어렵습니다).

또는

이 문서의 표에 대해 심각한 오해가 있어 개발자들은 테이블 값을 사용할 때 애초에 어떤 요점이 있었는지에 따라 무작위로 값을 선택했습니다.특히 이러한 값은 고려조차 되지 않는 방법으로 자신의 시드 값을 제공할 수 있기 때문입니다.

그래서 당신의 질문에 답하기 위해

이 두 숫자만큼 다른 숫자도 선택될 수 있었을까요?왜 그런가요? 혹은 왜 그렇지 않은가요?

예, 임의의 숫자를 사용할 수 있습니다.실제로 랜덤 인스턴스화 시 시드 값을 지정하면 다른 값을 사용합니다.이 값은 제너레이터의 성능에 영향을 미치지 않으며 클래스 내에서 하드 코딩된 a, c 및 m의 값에 의해 결정됩니다.

long은 2^128의 숫자를 가질 수 없기 때문에, 당신이 제공한 링크에 따라, 그들은 (누락된 1 : 를 추가한 후) 2^64 에서 최고의 수율을 선택했습니다.

언급URL : https://stackoverflow.com/questions/18092160/whats-with-181783497276652981-and-8682522807148012-in-random-java-7