문자열로 입력받는 것은
출력을 반대로 생각해주면 됩니다.
예로 문자열을 10진법으로 출력하기 위해
10으로 나누었다면
입력하기 위해서는
10씩 자리수만큼 곱하여 더하면 됩니다.
즉,
"1234"이라면
4 + 3 * 10 + 2 * (10^2) + 1 * (10^3)
다음과 같이 계산하면 됩니다.
여기서는 이것을 좀 더 확장하여
한번에 radix_a만큼 끊어서 읽으며
radix_b씩 자리수만큼 곱하여 더하는 식으로 하였습니다.
코드를 보시고 무슨 말인지 아실거라 믿습니다. ^^
>> 오버로딩 함수로는 10진법으로만 입력이 가능합니다.
10진법 이외로 입력을 받고 싶으시다면
먼저, string 에 입력을 받으신 다음
StringtoBigInteger함수에 첫번째 인수로 string을 넘기면 됩니다.
출력을 반대로 생각해주면 됩니다.
예로 문자열을 10진법으로 출력하기 위해
10으로 나누었다면
입력하기 위해서는
10씩 자리수만큼 곱하여 더하면 됩니다.
즉,
"1234"이라면
4 + 3 * 10 + 2 * (10^2) + 1 * (10^3)
다음과 같이 계산하면 됩니다.
여기서는 이것을 좀 더 확장하여
한번에 radix_a만큼 끊어서 읽으며
radix_b씩 자리수만큼 곱하여 더하는 식으로 하였습니다.
코드를 보시고 무슨 말인지 아실거라 믿습니다. ^^
const BigInteger & BigInteger::StringtoBigInteger(const string &str, const int radix/*=10*/) { // 2~36진법 모두로 입력 할 수 있습니다. // 단, 입력에서 발생할 수 있는 실수는 점검하지 않습니다! // 예로.. 1234a324aa32432a를 10진법으로 입력 한다면 // atoi 함수에서는 1234가 되지만 여기서는 4가 됩니다. if ( !( radix >=2 && radix <=36 ) ) throw "2 ~ 36진법까지만 가능합니다."; // *this를 0으로 초기화 합니다. // 0으로 초기화 하지 않으면 const char * // const string & 생성자에서 오류가 나며 // 이 함수를 따로 사용시에도 정확한 값이 나오지 않을 수 있습니다. Allocate(1); sign = Zero; // 문자열을 몇개씩 끊어서 읽을지 정합니다. length read_length = radix_a[radix - 2]; // 입력은 출력을 역으로 생각하면 됩니다. // 낮은자리부터 read_length씩 끊어 읽은것에 // base를 j번 곱해서 차례차례 결과값에 더하면 됩니다. BigInteger base(radix_b[radix - 2]); // 문자열의 길이를 구합니다. unsigned long offset = str.size(); // 밑의 _Copy_s 함수가 필요로 합니다. // 정확한 위치와 갯수를 인수로 넣어야 // 정확하고 오류없이 작동합니다. length blocklen = offset / read_length; unsigned long rest = offset % read_length; // read_length만큼 읽은것을 잠시 저장합니다. char temp[33] = {0,}; // 문자열에 진법이상의 숫자, 문자가 있는지 점검하기 위해서 사용합니다. char *error_ptr; BigInteger x; // 문자열 맨 앞에 부호가 있을 수 있습니다. // 부호가 있을 경우를 처리해 줍니다. unsigned long signexist = 0; if (str[0] == '+') // + 부호가 있다고 해서 sign를 대입받지 않습니다. signexist = 1; else if (str[0] == '-') { // "-0"과 같은 경우입니다. if (str.size() == 2 && str[1] == '0') return _Zero; // 그 밖에 음수면 부호를 대입합니다. signexist = 1; sign = Negative; } unsigned long i, j; i = 0; j = 0; // read_length씩 완전하게 끊어 읽을 수 있는 경우 // while문안으로 들어가게 됩니다. while (blocklen--) { // offset을 문자열의 맨 끝에서 // read_length만큼 빼줍니다. offset -= read_length; // offset에서 read_length만큼 읽어서 temp에 저장 str._Copy_s(temp, 33, read_length, offset); // strtoul함수는 진법으로 되있는 문자열을 // unsigned long형으로 바꿔줍니다. // 대입 연산자로 x에 잘 대입됩니다. x = strtoul(temp, &error_ptr, radix); // x에 base를 j번 곱합니다. // 자리수를 생각해야하기 때문입니다. while (j--) x *= base; add(*this, x); j = ++i; // 문자열에 진법 이상의 숫자,문자가 있으면 // goto로 함수를 종료시킵니다. // throw를 던지지 않습니다. if (*error_ptr != 0) goto endpoint; } // read_length에 부족하게 끊어 읽을 수 있는 경우 if (rest != 0) { memset(temp, 0, 33); offset -= (rest - signexist); if (signexist == 1) rest--; str._Copy_s(temp, 33, rest, offset); x = strtoul(temp, &error_ptr, radix); if (j != 0) { while (j--) x *= base; } add(*this, x); } endpoint: // 음수라면 부호가 Negative이며 // 나머지 경우는 모두 Zero로 되있습니다. // 그 중, 양수 조건을 만족시키면 부호를 바꿔줍니다. if ( !(len == 1 && blk[0] == 0) && sign != Negative) sign = Positive; return *this; }
>> 오버로딩 함수로는 10진법으로만 입력이 가능합니다.
10진법 이외로 입력을 받고 싶으시다면
먼저, string 에 입력을 받으신 다음
StringtoBigInteger함수에 첫번째 인수로 string을 넘기면 됩니다.
'프로젝트 > 큰수 클래스(Big Numerics)' 카테고리의 다른 글
[BigInteger - 19] 맺음 및 배포 (1) | 2011.07.14 |
---|---|
[BigInteger - 18] 업데이트 및 수정내용 (0) | 2011.07.14 |
[BigInteger - 16] 문자열로 출력하기 (0) | 2011.07.12 |
[BigInteger - 16] 나눗셈(Part 3) (0) | 2011.07.11 |
[BigInteger - 15] 나눗셈(Part 2) (0) | 2011.07.09 |