게시판 즐겨찾기
편집
드래그 앤 드롭으로
즐겨찾기 아이콘 위치 수정이 가능합니다.
컴게의 코딩의신님들 저좀 도와주세요...
게시물ID : computer_64493짧은주소 복사하기
작성자 : 광야의어린싹
추천 : 0
조회수 : 1141회
댓글수 : 7개
등록시간 : 2012/11/07 05:04:20

일반적인 큰정수 곱셈을 코딩했는데 이상한답이 나오네요.....지적질과 칼질 부탁드립니다.....







///////////////////////////////

///1.일반적인 큰 정수의 계산법///

///////////////////////////////


/*큰 정수 계산법 : 1. 큰 수를 담기위해 배열을 선언한다 그리고 인덱스가 큰배열로 제일큰 자릿수가 오도록 저장한다. ex(123456 => s[6][5][4][3][2][1]=123456)

2. 부호를 담기위한 int형을 선언한다.

 3.  (1,2)를 묶어서 Large_Integer형을 만든다. */




#include <stdio.h>

#include <stdlib.h>

#define DIGIT 100 // 최대한도 자릿수를 100자리까지 잡는다.


typedef struct large_integer// Large_Integer형

{

char n[DIGIT];   //저장시 숫자는 순서가 거꾸로 저장된다.

int p;          //양수 음수 판단.(true=음수 .false = 양수)

} LARGE_INTEGER;


char i_a(int a);  //정수를 알파벳으로 변환

int  a_i(char a); //알파벳을 정수로 변환

int Digit_Count(LARGE_INTEGER x); //입력한 수가 몇자리인지를 구하는 함수.

void Initial(LARGE_INTEGER &x); // 배열을 초기화

void Input_num(LARGE_INTEGER &x, LARGE_INTEGER &y); // 숫자입력.

void    Print_num(LARGE_INTEGER x); // 이용자가 보기 편하게 거꾸로 저장된 LARGE_INTERGER를 올바르게 출력.

void Reverse(LARGE_INTEGER &u); // 배열의 순서를 뒤집어준다.

void    JudgePlusMinus(LARGE_INTEGER &u);          //음수 양수를 판단해서 bool에 저장해준다.

LARGE_INTEGER CheckDigit(LARGE_INTEGER u);       //0을 없애준다.

LARGE_INTEGER Mul_Usual (LARGE_INTEGER u, LARGE_INTEGER v); // 일반적 방법으로 두 수 곱하기


void main()

{

LARGE_INTEGER u, v, x;    

Initial(u); Initial(v); Initial(x);

// u.v,x를 초기화해줍니다.


printf("첫번쨰 큰수 곱셈법\n");

Input_num(u, v);

//입력 및 배열에 거꾸로 저장


JudgePlusMinus(u); JudgePlusMinus(v);

//음수 양수를 판단해서 저장


printf("\n일반적인 곱셈법 : ");

Print_num(Mul_Usual(u,v));


}


int Digit_Count(LARGE_INTEGER x) // 자리수 구하기

{

int counter=0;  //자릿수를 세기위한 counter 변수


for(int i=0 ; i<=DIGIT-1 ; i++) // 배열에서 NULL 이 나올때까지 루프돌려서 자리수를 알아낸다.

{

if(x.n[i] != NULL)

counter++;

else

break;

}


return counter;

}


void Initial(LARGE_INTEGER &x) // 배열을 초기화.

{

for(int i=0 ; i<=DIGIT-1 ; i++)

{

x.n[i] = 0; // 모든 배열에 0을 넣어준다.

}

x.p = 0; // 부호의 기본값을 양수로 설정.

}


void Input_num(LARGE_INTEGER &x, LARGE_INTEGER &y) // 입력받고 음수양수 처리 및 배열 거꾸로 돌려 저장

{

scanf("%s %s", x.n, y.n);


Reverse(x);

Reverse(y);


}


void Print_num(LARGE_INTEGER x) // 거꾸로 돌리고 출력

{

Reverse(x);

if(x.p == 1)

printf("- %s",x.n);

else

printf("  %s",x.n);

}


void Reverse(LARGE_INTEGER &u) // 배열에 저장된 숫자를 거꾸로 되돌리기 and 음수 양수 저장

{

int digit = Digit_Count(u);

char temp[DIGIT];


    for(int i = 0 ; i<digit ; i++)  //거꾸로 temp배열에 저장

temp[i] = u.n[digit-i-1];


    for(int i = 0 ; i<digit ; i++)

u.n[i] = temp[i];



}


void JudgePlusMinus(LARGE_INTEGER &u) //양수 음수를 판단하여 0.1을 저장

{

int digit = Digit_Count(u);

if( u.n[(digit)-1] == '-') 

{

u.p = 1;  //음수 

u.n[(digit)-1]=NULL;

}

else

u.p = 0; //양수


}


LARGE_INTEGER Mul_Usual(LARGE_INTEGER u, LARGE_INTEGER v) // 일반적 방법으로 두 수 곱하기

{

LARGE_INTEGER result;

Initial(result);


int carry1=0;

int carry2=0;

    int digit1 = Digit_Count(u);

int digit2 = Digit_Count(v);

int digit3 = digit1+digit2;


result.n[digit3+1]=NULL;


Reverse(u);

Reverse(v);


    for(int i=digit1 -1;i>=0;i--)

{

int k=digit1+i;


for(int j=digit2-1; j>=0; j--,k--)

{


if(a_i(u.n[i]) * a_i(v.n[j]) >=10) //u와 v의 한자리 배열의 곱이 carry를 발생시킬떄

{

 carry1 = a_i(u.n[i]) * a_i(v.n[j]) / 10; //carry를 구해서 carry1에 저장


 if( ( a_i(u.n[i]) * a_i(v.n[j]) % 10  + carry2 + a_i(result.n[k]) ) >=10 )  //전 단계 carry + 배열곱셈의 나머지 + 결과배열 기존값의 합이 carry를 발생시킬떄

 {

  carry1 = carry1 + ( (a_i(u.n[i]) * a_i(v.n[j]) % 10  + carry2 + a_i(result.n[k]) ) / 10 );  // 기존 carry에 덧셈으로 인해 증가하는 carry값을 더함.

  result.n[k] = i_a( ( a_i(u.n[i]) * a_i(v.n[j]) % 10  + carry2 + a_i(result.n[k])) % 10 ); //해당 결과 배열에 carry하는 값을 뺸 나머지를 저장.

  carry2 = carry1;  //다음 연산시 carry를 더하기위한 대입.

 }

 else

 {

  result.n[k] = i_a(a_i(u.n[i]) * a_i(v.n[j]) % 10  + carry2 + a_i(result.n[k])); //더하기로 carry가 없기떄문에 그냥 나머지를 저장.

  carry2=carry1; //다음 연산시 carry를 더하기위한 대입.

 }

}

else

{

 carry1 = 0; //곱으로 인한 carry가 발생하지 않으므로 carry값은 0이다.


 if( ( a_i(u.n[i]) * a_i(v.n[j])  + carry2 + a_i(result.n[k]) ) >=10 )  //전 단계 carry + 배열곱셈의 나머지 + 결과배열 기존값의 합이 carry를 발생시킬떄

 {

carry1 = carry1 +  ( ( a_i(u.n[i]) * a_i(v.n[j]) + carry2 + a_i(result.n[k]) ) /10 );  //기존 carry에 덧셈으로 인해 증가하는 carry값을 더함.

result.n[k] = i_a( ( a_i(u.n[i]) * a_i(v.n[j]) + carry2 + a_i(result.n[k])) % 10 ); //해당 결과 배열에 carry하는 값을 뺸 나머지를 저장.

   carry2 = carry1;  //다음 연산시 carry를 더하기위한 대입.

 }

 else

 {

result.n[k] = i_a( a_i(u.n[i]) * a_i(v.n[j]) + carry2 + a_i(result.n[k]) ); //해당 결과 배열에 carry하는 값을 뺸 나머지를 저장.

   carry2 = carry1;  //다음 연산시 carry를 더하기위한 대입

 }

}

}

        result.n[k-1] = i_a( a_i(result.n[k-1]) + carry2 ); //for문안에서 못 계산한 carry를 계산.

carry2 = 0; //자릿수 계산이 완료햇기 떄문에 0으로 초기화

}


    Reverse(result);// 뒤집어서 저장

result=CheckDigit(result); //자리수 조정

return result; //결과 리턴

}


LARGE_INTEGER CheckDigit(LARGE_INTEGER u) // 배열 제일 오른쪽 큰 자리수가 0일 때 자리수 조정하기(EX : 123000 -> 123 )

{

LARGE_INTEGER result;

int digit = Digit_Count(u);

result = u;


for( int i = digit-1 ; i>0 ; i--)

{

if(result.n[i] == '0')

result.n[i] = NULL;

else break;


if(result.n[i-1] != '0')

break;


if(i == 1 || result.n[0] == '0')

result.n[1] = NULL;

}

return result;

}

int a_i(char a)

{

int re=0;

re=a-48;

return re;

}

char i_a(int a)

{

int re=0;

re=a+48;

return re;

}

전체 추천리스트 보기
새로운 댓글이 없습니다.
새로운 댓글 확인하기
글쓰기
◀뒤로가기
PC버전
맨위로▲
공지 운영 자료창고 청소년보호