로또 번호 조합기 원리와 경우의 수 계산: 고정수·제외수부터 Fisher-Yates 셔플 알고리즘까지

로또 번호, 왜 경우의 수를 알아야 할까
매주 로또를 구매할 때 순수 무작위 자동 추출을 이용하는 경우가 많지만, 자신이 분석한 기대 번호(고정수)나 출현 가능성이 낮다고 판단하는 번호(제외수)를 반영해 나만의 조합을 만들고 싶어 하는 분들도 있습니다.
문제는 고정수와 제외수를 지정했을 때 전체 경우의 수가 실제로 어떻게 줄어드는지, 그리고 남은 후보 중에서 번호를 뽑을 때 특정 번호가 더 자주 뽑히지 않도록 어떻게 공정하게 추출하는지가 잘 알려져 있지 않다는 점입니다. 아래에서 계산 원리와 실제 조합 생성 과정을 차례로 살펴봅니다.
경우의 수 계산과 공정한 번호 추출 원리
전체 경우의 수: C(45, 6)
로또 6/45는 1부터 45까지의 서로 다른 자연수 중 6개를 중복 없이, 순서에 상관없이 선택하는 조합(Combination) 구조입니다.
수학에서 n개 중 k개를 순서 없이 선택하는 조합 공식은 다음과 같습니다.
C(n, k) = n! ÷ (k! × (n - k)!)
이를 로또 6/45 조건에 대입하면 다음과 같이 전개됩니다.
C(45, 6) = (45 × 44 × 43 × 42 × 41 × 40) ÷ (6 × 5 × 4 × 3 × 2 × 1)
분자(45 × 44 × 43 × 42 × 41 × 40)는 5,864,443,200이고, 분모(6!)는 720이므로 최종 경우의 수는 다음과 같습니다.
C(45, 6) = 5,864,443,200 ÷ 720 = 8,145,060
즉, 1등에 당첨될 수학적 확률은 정확히 1/8,145,060(약 0.0000123%)입니다. 이는 814만 5천 60장의 서로 다른 조합을 모두 구매해야 그중 1장이 반드시 1등에 해당하는 수치입니다.
고정수·제외수를 지정하면 경우의 수가 어떻게 줄어드는가
내가 꼭 넣고 싶은 번호(고정수)나 절대 넣고 싶지 않은 번호(제외수)를 지정하면 후보군과 선택 슬롯이 함께 줄어듭니다.
전체 번호 개수를 45, 선택할 개수를 6, 고정수 개수를 m(0 ≤ m ≤ 6), 제외수 개수를 e라고 하면, 고정수 m개는 이미 6개 슬롯 중 m자리를 차지하므로 남은 슬롯은 (6 − m)개이고, 제외수 e개와 고정수 m개를 뺀 남은 후보 번호는 (45 − m − e)개가 됩니다. 따라서 축소된 경우의 수는 다음 공식으로 계산됩니다.
가능한 조합 수 = C(45 − m − e, 6 − m)
예시 1. 고정수 2개, 제외수 5개 남은 후보군은 45 − 2 − 5 = 38개, 선택할 슬롯은 6 − 2 = 4개이므로 다음과 같이 계산됩니다.
C(38, 4) = (38 × 37 × 36 × 35) ÷ (4 × 3 × 2 × 1) = 2,714,040 ÷ 24 = 73,815
단 2개의 고정수와 5개의 제외수만 지정해도 전체 경우의 수가 8,145,060개에서 73,815개로 크게 줄어듭니다.
예시 2. 고정수 3개, 제외수 10개 남은 후보군은 32개, 선택할 슬롯은 3개이므로 다음과 같습니다.
C(32, 3) = (32 × 31 × 30) ÷ (3 × 2 × 1) = 29,760 ÷ 6 = 4,960
고정수와 제외수를 늘릴수록 조합의 경우의 수는 이처럼 빠르게 줄어듭니다.
Fisher-Yates 셔플로 공정하게 번호 뽑기
경우의 수를 줄인 뒤 남은 후보군에서 번호를 뽑을 때 중요한 것은 모든 번호가 동일한 확률로 선택되는 공정성입니다.
흔히 쓰는 방식처럼 Math.random()으로 번호를 하나씩 무작위로 뽑아 중복을 제거하는 방법은 특정 숫자가 더 자주 뽑히는 편향(모듈로 편향)이 생기거나, 이미 뽑힌 번호가 계속 나와 while 루프가 불필요하게 반복되는 문제가 있을 수 있습니다.
Fisher-Yates(Knuth) 셔플은 크기가 N인 배열을 시간 복잡도 O(N)만에 완전히 무작위로 섞는 알고리즘으로, 모든 원소가 모든 위치에 올 확률이 정확히 1/N!로 균등하게 보장됩니다. 작동 순서는 다음과 같습니다.
- 후보 번호가 들어있는 배열 P를 작성합니다.
- 배열의 마지막 인덱스(i = N − 1)부터 i = 1까지 역순으로 훑어 내려갑니다.
- 0부터 i 사이의 임의의 정수 인덱스 j를 무작위로 선택합니다.
- P[i]와 P[j]의 위치를 서로 교환합니다.
- 셔플이 끝난 배열의 앞에서부터 필요한 개수만큼 순서대로 추출합니다.
로또 구매 시 인기가 높은 '반자동' 방식(일부 번호는 고정, 나머지는 무작위)도 이 원리를 그대로 활용합니다. 입력한 고정수와 제외수의 유효성을 검증한 뒤, 전체 번호 1~45에서 고정수 집합과 제외수 집합을 뺀 후보군을 만들고, 그 후보군에 Fisher-Yates 셔플을 적용해 필요한 개수만큼 뽑은 다음 고정수와 합쳐 오름차순으로 정렬하면 최종 조합이 완성됩니다.
직접 계산해보기: TypeScript 구현 예제
다음은 고정수와 제외수 필터링, Fisher-Yates 셔플을 반영한 로또 조합 생성 함수의 실제 구현 예제입니다.
/**
* 로또 6/45 커스텀 조합 생성 함수
* @param fixedNumbers 반드시 포함할 고정수 배열 (0~6개)
* @param excludedNumbers 제외할 번호 배열
* @returns 오름차순 정렬된 6개의 로또 번호 배열
*/
function generateLottoNumbers(
fixedNumbers: number[] = [],
excludedNumbers: number[] = []
): number[] {
// 1. 중복 제거 및 Set 변환
const fixedSet = new Set(fixedNumbers);
const excludedSet = new Set(excludedNumbers);
// 2. 입력값 유효성 검사
if (fixedSet.size > 6) {
throw new Error("고정수는 최대 6개까지 설정할 수 있습니다.");
}
for (const num of fixedSet) {
if (excludedSet.has(num)) {
throw new Error("고정수와 제외수에 중복된 번호(" + num + ")가 존재합니다.");
}
}
// 3. 남은 후보군(Candidate Pool) 생성
const candidatePool: number[] = [];
for (let i = 1; i <= 45; i++) {
if (!fixedSet.has(i) && !excludedSet.has(i)) {
candidatePool.push(i);
}
}
const neededRandomCount = 6 - fixedSet.size;
if (candidatePool.length < neededRandomCount) {
throw new Error("제외수가 너무 많아 6개 번호를 조합할 수 없습니다.");
}
// 4. Fisher-Yates 셔플 알고리즘 적용
const shuffled = [...candidatePool];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
// 5. 무작위 번호 추출 및 고정수와 병합
const selectedRandom = shuffled.slice(0, neededRandomCount);
const finalCombination = [...Array.from(fixedSet), ...selectedRandom];
// 6. 오름차순 정렬하여 반환
return finalCombination.sort((a, b) => a - b);
}
// 사용 예시: 고정수 [7, 14], 제외수 [3, 10, 21, 35, 42]
const myLottoNumbers = generateLottoNumbers([7, 14], [3, 10, 21, 35, 42]);
console.log("생성된 로또 번호:", myLottoNumbers);
위 코드처럼 Fisher-Yates 셔플을 사용하면 불필요한 반복 없이 항상 O(N)의 시간 복잡도로 공정한 무작위 조합을 만들 수 있습니다.
직접 코드를 작성해 계산할 수도 있지만, 고정수·제외수를 화면에서 클릭만으로 지정하고 여러 세트를 한 번에 만들고 싶다면 저희 도구로 확인하기.
무료 · 고정수/제외수 지정 · Fisher-Yates 공정 난수 추출
로또 번호 조합 시 참고할 만한 통계
수학적으로 8,145,060가지 조합의 당첨 확률은 모두 동일합니다. 다만 역대 당첨 번호의 출현 통계를 보면 다음과 같은 경향이 있습니다.
항목
통계
홀짝 비율 3:3 (홀수 3개, 짝수 3개)
전체 출현의 약 33%
홀짝 비율 4:2 (홀수 4개, 짝수 2개)
약 25%
홀짝 비율 2:4 (홀수 2개, 짝수 4개)
약 23%
홀짝 비율 5:1 (홀수 5개, 짝수 1개)
약 9%
홀짝 비율 1:5 (홀수 1개, 짝수 5개)
약 7%
홀짝 비율 6:0 (전체 홀수)
약 1.2%
홀짝 비율 0:6 (전체 짝수)
약 1% 미만
번호 합계 100~170 구간
약 80% 이상
연속된 두 숫자 1쌍 이상 포함
약 53%
즉 [3:3], [4:2], [2:4]처럼 균형 잡힌 홀짝 비율이 전체 당첨 번호의 대부분을 차지합니다.
또한 45개 번호를 10개 단위로 나눈 5개 구간(110, 1120, 2130, 3140, 41~45)에 번호가 고르게 분산될수록 실제 당첨 번호와 유사한 패턴이 되며, 특정 구간 한두 곳에 6개가 모두 몰리는 경우는 역사적으로 드물게 나타났습니다.
3연속 이상의 번호(예: 14, 15, 16)가 포함되는 경우도 출현 빈도가 낮은 편입니다.
이 통계는 특정 번호의 당첨 확률 자체를 바꾸지 않지만, 조합을 구성할 때 참고할 수 있는 정보입니다.
정리
로또 6/45의 전체 경우의 수는 8,145,060가지이며, 고정수와 제외수를 지정하면 이 경우의 수가 크게 줄어듭니다. 줄어든 후보군에서 번호를 뽑을 때는 Fisher-Yates 셔플과 같은 공정한 알고리즘을 사용해야 특정 번호가 더 자주 뽑히는 편향을 막을 수 있습니다.
홀짝 비율이나 번호 합계 같은 통계는 당첨 확률 자체를 바꾸지는 않지만, 조합을 구성할 때 참고할 수 있는 정보입니다. 계산 과정을 직접 코드로 구현할 수도 있지만, 고정수·제외수 지정과 셔플 과정을 자동화한 도구를 사용하면 더 빠르게 조합을 만들 수 있습니다.
무료 · 고정수/제외수 지정 · Fisher-Yates 공정 난수 추출
자주 묻는 질문
로또 번호 조합기는 어떻게 사용하나요?
45개의 번호판 그리드에서 마우스 클릭으로 포함할 번호(고정수, 초록색)와 제외할 번호(제외수, 빨간색)를 토글로 지정한 뒤, 생성할 조합 세트 개수(1~5게임)를 정하고 번호 조합 생성하기를 클릭하면 됩니다. 결과 화면에서 조합 리스트와 함께 홀수·짝수 구성비, 번호 합계 구간 분석을 확인할 수 있습니다.
번호 합계(Sum Range)는 왜 함께 보여주나요?
역대 로또 6/45 당첨 번호의 전체 합산 분포를 보면 6개 수의 합이 100~170 사이인 경우가 전체의 80% 이상을 차지합니다. 도구는 생성된 조합의 합계가 이 구간에 속하는지 함께 보여줘 균형 잡힌 조합인지 참고할 수 있게 합니다.
고정수를 설정하면 당첨 확률이 올라가나요?
아니요. 로또 6/45에서 만들어질 수 있는 8,145,060가지 조합은 어떻게 구성하든 당첨 확률이 정확히 1/8,145,060로 모두 동일합니다. 고정수를 지정하는 것은 이 조합들 중 내가 원하는 번호를 포함한 부분집합만 골라서 플레이하는 것일 뿐, 그렇게 만든 조합 자체의 당첨 확률을 수학적으로 높여주지는 않습니다. 다만 여러 세트를 한 번에 구매할 때 선호하는 번호를 고정해두면 원하는 조건으로 후보를 좁혀 관리하기 편리하다는 실용적인 이점은 있습니다.
이 도구로 생성한 번호는 무작위인가요?
네, Fisher-Yates 셔플 알고리즘을 기반으로 조합을 생성하므로 특정 번호가 더 자주 뽑히는 편향 없이 후보군 내에서 공정하게 번호를 추출합니다.
본 가이드에서 제공하는 정보는 수학적 경우의 수 계산과 통계적 정보 제공을 목적으로 작성되었습니다.
