나누기 함수는 기본적으로
몫과 나머지를 동시에 구할 수 있습니다.
나머지->divideWithRemainder(나누는 수, 몫);
같은 형태로 사용하기 때문입니다.
/, % 연산자 오버로딩 함수는 초기나 지금이나 변화가 없기 때문에 뒤에서 언급하겠습니다.
초기 나누기 알고리즘을 간략하게 설명하면..
1. 초등학교 때 배웠던 사용하던 방식을 사용합니다.
2. 쉬프트 함수와 빼기 함수를 이용해 나누기를 진행합니다.
3. 예..(2진수의 나눗셈입니다.)
피제수 = 1 0010 1010 (298)을 제수 = 1100 (12)로 나누어 보겠습니다.
ㄱ. 피제수의 비트수는 9
ㄴ. 제수의 비트수는 4
ㄷ. 몫이 될 수있는 최고 자릿수는 9(피제수비트수) - 4(제수비트수) = 5(i)번째부터 가능
ㄹ. 제수를 왼쪽으로 5(i)쉬프트, 1100 << 5(i) = 110000000
ㅁ. 피제수와 제수를 비교
1. 피제수가 크거나, 같으면
ㄱ. 피제수에다가 제수만큼을 빼준다.
ㄴ. 몫의 낮은자리부터 i번째 비트가 1이된다.
ㅂ. 제수를 오른쪽으로 한칸 쉬프트
ㅅ. i가 0인지 비교
1. 0이면 ㅁ.~ㅅ. for문 완료!
2. 0이 아니면 i를 1감소시키고, ㅁ.으로 돌아가기
ㅇ. 몫과 나머지의 부호를 구한다.
ㅈ. 몫은 zapLeadingZeros함수를 호출한다.(나머지는 뺄셈함수내에서 호출하므로 할 필요 없다.)
ㄱ. ~ ㅈ. 까지가 알고리즘의 전체입니다.
저렇게 하면 298과 12의 나눗셈을 하게 되고
몫과 나머지가 각각 함수의 두번째 인수, 함수를 호출한 변수에 저장됩니다.
이것을 코드로 구현하면 다음과 같습니다.
몫과 나머지를 동시에 구할 수 있습니다.
나머지->divideWithRemainder(나누는 수, 몫);
같은 형태로 사용하기 때문입니다.
/, % 연산자 오버로딩 함수는 초기나 지금이나 변화가 없기 때문에 뒤에서 언급하겠습니다.
초기 나누기 알고리즘을 간략하게 설명하면..
1. 초등학교 때 배웠던 사용하던 방식을 사용합니다.
2. 쉬프트 함수와 빼기 함수를 이용해 나누기를 진행합니다.
3. 예..(2진수의 나눗셈입니다.)
피제수 = 1 0010 1010 (298)을 제수 = 1100 (12)로 나누어 보겠습니다.
ㄱ. 피제수의 비트수는 9
ㄴ. 제수의 비트수는 4
ㄷ. 몫이 될 수있는 최고 자릿수는 9(피제수비트수) - 4(제수비트수) = 5(i)번째부터 가능
ㄹ. 제수를 왼쪽으로 5(i)쉬프트, 1100 << 5(i) = 110000000
ㅁ. 피제수와 제수를 비교
1. 피제수가 크거나, 같으면
ㄱ. 피제수에다가 제수만큼을 빼준다.
ㄴ. 몫의 낮은자리부터 i번째 비트가 1이된다.
ㅂ. 제수를 오른쪽으로 한칸 쉬프트
ㅅ. i가 0인지 비교
1. 0이면 ㅁ.~ㅅ. for문 완료!
2. 0이 아니면 i를 1감소시키고, ㅁ.으로 돌아가기
ㅇ. 몫과 나머지의 부호를 구한다.
ㅈ. 몫은 zapLeadingZeros함수를 호출한다.(나머지는 뺄셈함수내에서 호출하므로 할 필요 없다.)
ㄱ. ~ ㅈ. 까지가 알고리즘의 전체입니다.
저렇게 하면 298과 12의 나눗셈을 하게 되고
몫과 나머지가 각각 함수의 두번째 인수, 함수를 호출한 변수에 저장됩니다.
이것을 코드로 구현하면 다음과 같습니다.
void BigInteger::divideWithRemainder(const BigInteger &Divisor, BigInteger &Quotient) { length Divided_BitLen, Dividor_BitLen; Divided_BitLen = bitlength(); // 피제수(나누어지는 수)의 비트길이 Dividor_BitLen = Divisor.bitlength(); // 제수(나누는 수)의 비트길이 // 제수의 비트길이가 더 길면 // 연산을 할 필요 없습니다. // 몫은 0, 나머지는 *this가 됩니다. if (Divided_BitLen < Dividor_BitLen) { Quotient = _Zero; return; } /* * 나눗셈도 초등학교때 배운방법을 적용합니다. * * 776 * ---------- * 159 | 123456 * 111300 * ------ * 12156 * 11130 * ------- * 1026 * 954 * ------ * 72 */ // 몫의 최대 가능한 길이만큼 재할당합니다. // 피제수가 n비트, 제수가 m비트라면 // 몫의 최대 가능 비트는 n - m비트 입니다. // 블럭의 개수로 표현하면 (n - m)/32 + 1 입니다. Quotient.Reallocate( (Divided_BitLen - Dividor_BitLen)/N + 1 ); // const BigInteger & 형으로 받은 제수를 변경을 위해 temp에 저장합니다. BigInteger temp(Divisor); // 몫이 위치할 수 있는 제일 높은 자리는 i length i = (Divided_BitLen - Dividor_BitLen); temp <<= i; // i자리부터 한자리씩 낮춰가며 // *this에서 temp를 뺄 수 있는지 확인한다. do {/ if (CompareTo(temp) != Less)// *this >= temp 라면.. { // *this의 크기에서 temp의 크기만큼 뺌 subtract(*this, temp); // 몫의 i번째 자리가 1이 된다. Quotient.blk[i >> 5] |= blocktype(1) << ( i & 31); } // temp를 오른쪽으로 한칸 쉬프트 temp >>= 1; }while (i-- > 0); // i부터 0까지 계속 반복 Quotient.ZapLeadingZeros(); Quotient.sign = (sign == Divisor.sign) ? Positive : Negative; if (Quotient.len == 1 && Quotient.blk[0] == 0) Quotient.sign = Zero; if (len == 1 && blk[0] == 0) sign = Zero; }
'프로젝트 > 큰수 클래스(Big Numerics)' 카테고리의 다른 글
[BigInteger - 16] 문자열로 출력하기 (0) | 2011.07.12 |
---|---|
[BigInteger - 16] 나눗셈(Part 3) (0) | 2011.07.11 |
[BigInteger - 14] 나눗셈(Part 1) (0) | 2011.07.08 |
[BigInteger - 13] 곱셈 (0) | 2011.07.08 |
[BigInteger - 12] 뺄셈 (0) | 2011.07.08 |