2012-03-04 2 views
2

제가난수가 고유하고 중복되지 않도록하는 방법은 무엇입니까?

난수
SecureRandom random = new SecureRandom(); 
... 
public int getRandomNumber(int maxValue) { 
    return random.nextInt(maxValue); 
} 

상기 (하지 루프)의 약 10 배라고하는 방법을 생성하는 간단한 코드를 갖는다. 모든 숫자가 고유하다는 것을 확인하고 싶습니다 (maxValue > 1000으로 가정).

전화 할 때마다 고유 한 번호를 얻을 수 있습니까? 그렇지 않다면 어떻게 해결할 수 있습니까?

편집 : 나는 그것을 모호하게 말할지도 모른다. 고유 번호가있는 경우 수동 검사를 피하고 더 나은 솔루션이 있는지 궁금합니다.

+10

무작위! = 고유. 사실, 꽤 정반대입니다. –

+1

이전에 사용했던 번호를 확인한 후 해제하거나 임의 번호가 아닌 임의의 * 임의 번호를 사용하십시오. 당신이 단지 10 개의 숫자를 얻는다면 후자는 과잉이다. 위의 두 번째 문제, 즉 무작위성과 독창성이 있기 때문에 나는 Oli의 두 번째 반응에 대해 답합니다. –

+0

고유 한 대 임의의 용어를 지우는 질문을 편집했습니다. – skaffman

답변

5

이 방법은 여러 가지 방법이 있지만 더 적합한 방법은 몇 개를 선택해야하는지에 따라 다릅니다.

  • 잠재적 인 숫자의 큰 범위에서 임의의 숫자의 소수를 선택하는 경우에, 당신은 아마 세트에서 최고의 단지 저장 이전에 선택한 숫자이고 "수동"중복 검사합니다. 대부분의 경우, 실제로 복제본을 얻지는 못하며 실제적으로 비용이 거의 들지 않습니다. 그것은 우아하지 않게 들릴지 모르지만 실제로 들리는 것만 큼 나쁘지는 않습니다.
  • 일부 기본 난수 생성 알고리즘은 "원시"수준에서 중복을 생성하지 않습니다. 예를 들어, XORShift 생성기라고하는 알고리즘은 특정 범위 내의 모든 숫자를 효과적으로 생성 할 수 있으며 중복없이 셔플 처리됩니다. 따라서 기본적으로 시퀀스에서 임의의 시작점을 선택하고 다음 n 개의 숫자를 생성하면 중복되지 않습니다. 그러나이 경우에는 "최대"를 임의로 선택할 수 없습니다. 문제의 발전기의 자연 최대 값이어야합니다.
  • 가능한 숫자의 범위가 작지만 선택해야하는 숫자의 수가 해당 범위의 몇 자리수 이내이면이 값을 임의의 선택 문제로 처리 할 수 ​​있습니다.예를 들어, 중복없이 범위 10,000,000 내 10 만 개 번호를 선택,이 작업을 수행 할 수 있습니다

    하자 m은 내가 지금까지

    를 들어 I = 1 천만

    에 선택한 임의의 숫자의 숫자 범위

    랜덤 (부동 소수점)를 생성 할 수, R, 0-1

    (R < (10-m)은/(10,000,000이-1)), 그리스트에 난을 추가하는 경우 및 증분 m

이 필요하지만 당신은 어떤 합리적으로 큰 비율을 선택해야하는 경우 분명 만 많은 점은 후자의 옵션을 선택에 거기로 다음 목록에서 번호를 순차적으로 선택 목록을 셔플 전체 숫자 범위. 1 ~ 10 억의 범위에있는 10 개의 숫자를 선택하면, 당신이 가면서 중복을 확인함으로써 실제로 복제본을 얻지 못할 것이고 10 개의 무작위로 생성 될 것입니다. 번호.

+0

정말 도움이됩니다. XORShift가 재미있어합니다. 고맙습니다 – user219882

1

임의 순서는 모든 값이 고유하다는 의미는 아닙니다. 시퀀스 1,1,1,1은 시퀀스 712,4,22,424과 똑같습니다.

다른 말로하면 고유 번호의 시퀀스를 보장하려면 한 번에 10 개를 생성하고 원하는 고유성 조건을 확인하여 저장 한 다음 해당 고유성 조건을 생성하는 대신 해당 목록에서 숫자를 선택하십시오. 10 개 장소의 임의 번호.

0

작은 값의 경우, 간단한 구현은 1000 개의 정수를 목록에 넣고 각 반복마다 0에서 list.size() 사이의 임의의 숫자를 생성하는 루프를 가지며 저장된 숫자를 선택합니다 이 인덱스에서 목록에서 제거하십시오.

+0

나는 당신의 답을 따르고 당신이 그런 공헌자 인 것을 많이 배웠다. 이미 생성 된 숫자에 대한 1000 개의 정수 목록과 조회가 값 비싼 것이 아닌가? – kosa

+0

이 모든 것이 얼마나 많은 시간에 호출되는지에 따라 다르며, 상황에 따라 달라집니다. 10 억 회라는 긴밀한 루프에서 수행되면 더 나은 접근 방법을 선택하는 것이 유용 할 수 있습니다. 사용자 입력을 기다리는 데 대부분 한 번만 소비되는 응용 프로그램이나 한 두 번만 수행하면됩니다. (추신 : 나는 팬이 있다는 것을 몰랐다 ;-)) –

+0

분석과 답변은 팬 기반 가치가있다. 하하!. 나는 대답을하지만 대답은 A-G에서 멈추고 대답은 전체 기지 A-Z를 다룹니다. 모두 제일 좋다. – kosa

1

전화 할 때마다 Random#nextInt(int) 당신은

의사 난수, 0 (포함) 사이에 균일하게 분포 된 int 값 지정된 값 (전용)를 얻을 것이다.

x 고유 번호가 필요하면 그 번호를 얻을 때까지 새 번호를 계속 가져온 다음 해당 목록에서 "임의"번호를 선택하십시오. 그러나 생성 된 숫자를 필터링하고 있기 때문에 더 이상 임의적이지는 않습니다.

0

이 코드는 CPU를 메모리 비용으로 처리하는 경우 매우 효율적입니다. 각각의 가치는 sizeof(int) * maxValue입니다. 부호없는 정수는 최대 65535까지 작동합니다. long은 16 비트 정수 1000 값에 대해 많은 메모리 2000 바이트를 사용하여 사용할 수 있습니다.

배열의 전체 목적은 당신이 전에이 값을 사용하거나이 말을하지 1 = yes '다른 것 = 전혀 '고유 한 값을 찾을 때까지 난수를 생성하는 유지됩니다 while 루프. '좋은 임의의 값을 찾은 후에 그것을 사용한 것으로 표시하고 그것을 반환합니다. '변수의 범위가 어레이가 지울 수있는 범위를 벗어나는 것처럼주의하십시오. '나는 이것을 C에서 사용했으며 작동한다. '을 (를) Java에서 작동 시키려면 약간의 닦기가 필요할 수 있습니다.

unsigned int a(1000); 

public int getRandomNumber(int maxValue) { 
    unsigned int rand; 

    while(a(rand)==1) { 
    rand=random.nextInt(maxValue); 
    if (a(rand)!=1) { a(rand)=1; return rand;} 
    } 

} 
관련 문제