C++ 문법

C++ BigInteger 구현

슬뷔 2024. 1. 4. 18:41

https://blog.naver.com/tybnasgo/223006793286

 

BigInt 프로젝트 후기

- 프로젝트 배경 제가 하는 알고리즘 스터디에서 누군가 매우 큰 정수의 사칙연산에 관해 질문을 했었습니...

blog.naver.com

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//큰 수 클래스
class bigInt {
private:
    string number;//숫자
public:
    bigInt(string n = "");//생성자
    inline int max(int a, int b);//min
    void Show() const;//결과
    bool operator<(const bigInt& num);//<
    bool operator>(const bigInt& num);//>
    bigInt operator+(const bigInt& num);//+
    bigInt operator-(const bigInt& num);//-
    bigInt operator*(const bigInt& num);//*
    bigInt operator/(const bigInt& num);// /
    bigInt operator%(const bigInt& num);//%
};
//생성자
bigInt::bigInt(string n) {
    number = n;
}
//max
inline int bigInt::max(int a, int b) {
    return a > b ? a : b;
}
//계산 결과
void bigInt::Show() const {
    cout << number << "\n";
}
//n1 < n2
bool bigInt::operator<(const bigInt& n) {
    string n1 = this->number;//
    string n2 = n.number;
    int n1_size = n1.size(); int n2_size = n2.size();

    if (n1_size < n2_size) return true;//n2의 자릿수가 더 크다
    else if (n1_size > n2_size) return false;//n1의 자릿수가 더 크다
    else {//자릿수가 같다
        for (int i = 0; i < n1_size; i++) {//각 자릿수 비교
            if ((n1[i] - '0') < (n2[i] - '0')) return true;
            else if ((n1[i] - '0') > (n2[i] - '0')) return false;
        }
    }
    return false;
}
//n1 > n2
bool bigInt::operator>(const bigInt& n) {
    string n1 = this->number;//
    string n2 = n.number;
    int n1_size = n1.size(); int n2_size = n2.size();

    if (n1_size < n2_size) return false;//n2의 자릿수가 더 크다
    else if (n1_size > n2_size) return true;//n1의 자릿수가 더 크다
    else {//자릿수가 같다
        for (int i = 0; i < n1_size; i++) {//각 자릿수 비교
            if ((n1[i] - '0') > (n2[i] - '0')) return true;
            else if ((n1[i] - '0') < (n2[i] - '0')) return false;
        }
    }
    return false;
}
//+
bigInt bigInt::operator+(const bigInt& n) {
    bigInt ans;//최종 결과
    string res = "";//계산 결과
    string n1 = this->number;
    string n2 = n.number;
    int n1_size = n1.size(); int n2_size = n2.size();
    //두 문자열의 사이즈를 같게한다.(ex, 1999, 14=>1999 ,0014)
    string zero = "";
    if (n1_size < n2_size) {
        for (int i = 0; i < n2_size - n1_size; i++) zero += '0';
        n1 = zero + n1;
    }
    else if (n1_size > n2_size) {
        for (int i = 0; i < n1_size - n2_size; i++) zero += '0';
        n2 = zero + n2;
    }
    //일의 자리수부터 더해나간다.
    int cal_size = max(n1_size, n2_size);//계산 사이즈
    int up = 0;//받아 올림 여부
    //계산
    for (int i = 1; i <= cal_size; i++) {
        int dit = (n1[cal_size - i] - '0') + (n2[cal_size - i] - '0') + up;
        if (dit >= 10) {
            dit -= 10;
            up = 1;
        }
        else up = 0;
        res += to_string(dit);
    }
    if (up == 1) res += to_string(up);
    //문자열 바로 붙이기
    for (int i = res.size() - 1; i >= 0; i--) ans.number += res[i];
    return ans;
}
//-
bigInt bigInt::operator-(const bigInt& n) {
    bigInt ans;//최종 결과
    string res = "";//계산 결과
    string n1 = this->number;
    string n2 = n.number;
    int n1_size = n1.size(); int n2_size = n2.size();
    //두 문자열의 사이즈를 같게한다.(ex, 1999, 14=>1999 ,0014)
    string zero = "";
    if (n1_size < n2_size) {
        for (int i = 0; i < n2_size - n1_size; i++) zero += '0';
        n1 = zero + n1;
    }
    else if (n1_size > n2_size) {
        for (int i = 0; i < n1_size - n2_size; i++) zero += '0';
        n2 = zero + n2;
    }
    //일의 자리수부터 뺄셈을 한다.
    int cal_size = max(n1_size, n2_size);//계산 사이즈
    int down = 0;//받아 내림 여부
    //계산
    for (int i = 1; i <= cal_size; i++) {
        int dit = (n1[cal_size - i] - '0') - (n2[cal_size - i] - '0') - (down / 10);
        if (dit < 0) {//음수여서 받아 내림을 해야한다.
            dit += 10;
            down = 10;
        }
        else down = 0;
        res += to_string(dit);
    }
    //앞 0제거
    int zeroIndex = 0;//답이 0일 수 있다.
    for (int i = res.size() - 1; i >= 0; i--) {
        if (res[i] != '0') {
            zeroIndex = i;
            break;
        }
    }
    //문자열 바로 붙이기
    for (int i = zeroIndex; i >= 0; i--) ans.number += res[i];
    return ans;
}
//*
bigInt bigInt::operator*(const bigInt& n) {
    bigInt ans;//최종 결과
    string n1 = this->number;
    string n2 = n.number;
    int n1_size = n1.size(); int n2_size = n2.size();

    //0을 곱함
    if (n1 == "0" || n2 == "0") {
        ans.number = "0";
        return ans;
    }
    //계산 결과 배열 할당
    vector<vector<int>> mulArray;
    for (int j = 0; j < n2_size; j++) {
        vector<int> zero;
        for (int i = 0; i < n1_size; i++) zero.push_back(0);
        mulArray.push_back(zero);
    }

    //초등학교 알고리즘 적용(o(n2))
    for (int j = 0; j < n2_size; j++) {
        for (int i = 0; i < n1_size; i++) mulArray[n2_size - j - 1][i] = (n1[i] - '0') * (n2[j] - '0');
    }
    //열 증가
    string res = "";
    int digit = 0;//결과 값
    for (int k = n1_size - 1; k >= 0; k--) {//기준점
        int row = 0; int col = k;//기준 좌표
        //대각선으로 더하기
        while (col - row == k) {
            digit += mulArray[row][col];
            col++; row++;
            if (row >= n2_size || col >= n1_size) break;//배열 범위 초과
        }
        res += to_string(digit % 10);//문자열 붙이기
        digit = digit / 10;
    }
    //행 증가
    for (int k = 1; k < n2_size; k++) {//기준점
        int row = k; int col = 0;//기준 좌표
        //대각선으로 더하기
        while (row - col == k) {
            digit += mulArray[row][col];
            col++; row++;
            if (row >= n2_size || col >= n1_size) break;//배열 범위 초과
        }
        res += to_string(digit % 10);//문자열 붙이기
        digit = digit / 10;
    }
    //문자열 바로 붙이기(up, 맨 앞자리에 오는것부터)
    if (digit > 0) ans.number += to_string(digit);
    for (int i = res.size() - 1; i >= 0; i--) ans.number += res[i];
    return ans;
}
// / (n1/n2), 몫 구하기
bigInt bigInt::operator/(const bigInt& n) {
    bigInt ans;//최종 결과
    string n1 = this->number;//나눠야하는 수
    bigInt n2 = n.number;//나누는 수
    int n1_size = n1.size();//n1의 자릿수

    if (n2.number == "0") return ans.number = "INF\n";//0으로 나눔
    if ((bigInt)n1 < n2) return ans.number = "0";//몫이 0

    //몫이 존재, 초등학교 알고리즘 적용
    string share = "";//몫
    string divided; bigInt dividNum; bigInt ten;
    dividNum.number = "0";
    for (int i = 0; i < n1_size; i++) {
        divided = n1[i];//나눗셈을 진행할 문자열
        ten.number = "10";//10
        dividNum = dividNum * ten + (bigInt)(divided);//나누어지는 수
        if (dividNum < n2) share += to_string(0);//0 출력
        else {//나눌 수 있음
            int minusCount = 0;
            while (true) {
                if (dividNum < n2) break;//뺄셈 종료
                dividNum = dividNum - n2;
                minusCount++;
            }
            share += to_string(minusCount);//몫 구하기
        }
    }
    //출력
    int frontZero = 0;//맨 앞이 0
    for (int i = 0; i < share.size(); i++) {
        if (share[i] != '0') {
            frontZero = i;
            break;
        }
    }
    ans.number = share.substr(frontZero);//정답
    return ans;
}
//% (n1%n2), 나머지 구하기
bigInt bigInt::operator%(const bigInt& n) {
    bigInt ans;//최종 결과
    string n1 = this->number;//나눠야하는 수
    bigInt n2 = n.number;//나누는 수
    int n1_size = n1.size();//n1의 자릿수

    if (n2.number == "0") return ans.number = "NO\n";//0으로 나눔, 나머지가 존재하지 않음
    if ((bigInt)n1 < n2) return ans.number = n1;//몫이 0이므로 n1 그대로

    //몫이 존재, 초등학교 알고리즘 적용
    string divided; bigInt dividNum; bigInt ten;
    dividNum.number = "0";
    for (int i = 0; i < n1_size; i++) {
        divided = n1[i];//나눗셈을 진행할 문자열
        ten.number = "10";//10
        dividNum = dividNum * ten + (bigInt)(divided);//나누어지는 수
        if (dividNum < n2) {}
        else {//나눌 수 있음
            while (true) {
                if (dividNum < n2) break;//뺄셈 종료
                dividNum = dividNum - n2;
            }
        }
    }
    ans = dividNum;//정답
    return ans;//나머지
}
int main()
{
    string s1, s2;
    cin >> s1 >> s2;
    bigInt x(s1), y(s2);//큰 수 정의
    //크기 비교
    if (x > y) cout << "x승\n";
    else cout << "y승\n";
    //덧셈
    bigInt add = x + y;
    add.Show();
    //뺄셈
    bigInt minus = x - y;
    minus.Show();
    //곱셈
    bigInt multi = x * y;
    multi.Show();
    //나눗셈
    bigInt division = x / y;
    division.Show();
    //나머지
    bigInt rest = x % y;
    rest.Show();
    return 0;
}

https://m.blog.naver.com/dlscjs8646/222154699653

 

2338) 긴자리 계산 - C++, Python

※ Python3 버전 ※ C++17 버전 또 속았다. 이래도 이번엔 알고 속았다. 제일 어려운 나눗셈을 했으니 덧...

blog.naver.com

#include <iostream>
#include <cstring> // strlen 사용을 위해서 가져옴!!

// strlen은 문자열의 길이를 가져오는 기본 메소드

int bigger(char* a, char* b) { // a가 b보다 절대값이 큰 지 여부를 확인하는 메소드 (a가 크면 1, b가 크면 0, 같으면 2)
	if (strlen(a) > strlen(b)) // a가 더 길면 1 반환
		return 1;
	else if (strlen(a) < strlen(b)) // b가 더 길면 0 반환
		return 0;
	else { // 길이가 같다면?
		for (int i = 0; i < strlen(a); i++) { // 첫자리부터 하나하나 비교해서 살펴봄
			if (a[i] > b[i]) // a가 더 크면 1 반환
				return 1;
			else if (a[i] < b[i]) // b가 더 크면 0 반환
				return 0;
		}
	}
	return 2; // 같으면 2 반환
}



void add(char* a, char* b) { // 문자열 내의 숫자를 더하는 경우 (무조건 a가 더 크다고 생각)
	int r[1010] = { 0 }; // 정수형 배열, 배열 내부 0으로 초기화
	int i = strlen(a) - 1; //  a의 길이 -1을 i에 넣어준다.

	for (int j = strlen(b) - 1; j >= 0; j--) { // b의 길이 -1를 j에 넣어준다
		if (i >= 0) {
			r[i] = (a[i] - '0') + (b[j] - '0'); // a와 b에서 각각 0의 아스키코드를 뺀다음 둘을 더해준다. (문자열이니 아스키코드계산)
		}
		i--; // i랑 j 둘다 빼줘야하니 따로 빼준다.
	}

	for (; i >= 0; i--) // 길이 차이때문에 안들어간 부분 넣어주기
		r[i] = a[i] - '0'; // 문자열이니 아스키코드임을 주의하자!

	for (int i = strlen(a) - 1; i > 0; i--) { // 0이 들어가지 않는 이유는 결과값의 0번 인덱스의 값은 2자리여도 상관없기 때문!!
		if (r[i] > 9) { // 만약 9보다 크면
			r[i] -= 10; // 10을 뺀다
			r[i - 1]++; // 앞자리 수를 1 키운다
		}
	}

	for (int i = 0; i < strlen(a); i++) { // 출력! 더했을 때는 0끼리 더하지 않는 이상 r[0]이 0이 될 수 없고, 0끼리 더해도 0이 잘 출력되므로 따로 0의 경우를 고려하지 않아도 된다
		std::cout << r[i];
	}

	std::cout << std::endl; // 엔터
}



void subtract(char* a, char* b) { // 문자열 내의 숫자를 빼는 경우 (무조건 a가 더 크다고 생각)
	int r[1010] = { 0 }; // 정수형 배열, 배열 내부 0으로 초기화
	int i = strlen(a) - 1; //  a의 길이 -1을 i에 넣어준다.
	bool chk = false; // 0 체크용 부울변수

	for (int j = strlen(b) - 1; j >= 0; j--) { // b의 길이 -1를 j에 넣어준다
		if (i >= 0) {
			r[i] = (a[i] - '0') - (b[j] - '0'); // a와 b에서 각각 0의 아스키코드를 뺀다음 둘을 빼준다. (문자열이니 아스키코드계산)
		}
		i--; // i랑 j 둘다 빼줘야하니 따로 빼준다. 덧셈과 같은 원리
	}

	for (; i >= 0; i--) // 길이 차이때문에 안들어간 부분 넣어주기
		r[i] = a[i] - '0'; // 문자열이니 아스키코드임을 주의하자!

	for (i = strlen(a) - 1; i > 0; i--) { // 0이 들어가지 않는 이유는 절대값 a가 절대값 b보다 크기 때문에 r[0]이 0보다 작아질 수 없기 때문에 확인할 필요가 없다.
		if (r[i] < 0) { // 만약 0보다 작아지면
			r[i] += 10; // 10을 더한다
			r[i - 1]--; // 앞자리 수를 1 뺀다
		}
	}

	for (i = 0; i < strlen(a); i++) { // r 내의 모든 요소가 0이라면, chk는 false로 남아있게 된다.
		if (r[i] != 0)
			chk = true;
	}

	if (!chk) { // 만약 이 chk가 false면 0을 출력한다.
		std::cout << 0;
	}

	else { // 그게 아니라면
		for (i = 0; r[i] == 0; i++); // 앞쪽에 있는 0들을 제끼고
		for (; i < strlen(a); i++) { // 유효한 숫자부터 출력한다.
			std::cout << r[i];
		}
	}
	std::cout << std::endl; // 엔터
}



void multiple(char* a, char* b) { // 일반적인 계산방식은 이중 for문이라 O(n^2), 카라츠바 알고리즘을 쓰면 O(n^log3)까지 단축할 수 있다. 이건 일반 방식!
	int r[2020] = { 0 }; // 배열 0으로 초기화
	bool chk = false; // 0 체크용 부울변수

	// 우리가 초등학교때 곱셈계산하듯이 각 자리별로 곱해서 배열에 더해준다.
	// 현실에서는 일반적으로 이 알고리즘과는 반대로 1의 자리부터 A에다가 곱한 후 더해주기 때문에 헷갈릴 순 있지만, 결과적으로 값은 똑같다.)
	for (int i = 0; i < strlen(a); i++) {
		for (int j = 0; j < strlen(b); j++) {
			r[i + j] += (a[i] - '0') * (b[j] - '0'); // a와 b에서 각각 0의 아스키코드를 뺀다음 둘을 곱해서 더해준다. (문자열이니 아스키코드계산, 여러번 더해야 하므로 =이 아니라 +=임에 주의!!)
		}
	}

	for (int i = strlen(a) + strlen(b) - 1; i > 0; i--) { // 첫항 빼고는 10으로 나눈 나머지만 남긴다. 몫은 이전항으로 넘겨버린다. (첫항은 2자리까지 나올 수 있다!!)
		// n자리*n자리는 최대 2n자리까지 나올 수 있으니까 n+n-1만큼의 자리로 2n자리를 표기하기 위해서는 어딘가에는 2자리를 적어야하는데 그게 첫항!!)
		r[i - 1] += r[i] / 10; // 몫(carry값)
		r[i] = r[i] % 10; // 나머지
	}

	for (int i = 0; i < strlen(a); i++) { // r 내의 모든 요소가 0이라면, chk는 false로 남아있게 된다.
		if (r[i] != 0)
			chk = true;
	}

	if (!chk) { // 만약 이 chk가 false면 0을 출력한다.
		std::cout << 0;
	}

	else {
		// strlen 두개를 더한 값의 -1만큼만 출력해야 값이 있는 부분만 출력할 수 있다.
		// 첫항에서 1자리와 2자리 모두 나올 수 있기 때문에 배열 요소는 항상 같은 갯수만큼 출력해도 된다.
		for (int i = 0; i < strlen(a) + strlen(b) - 1; i++) {
			std::cout << r[i];
		}
	}
}

int main() {
	// 배열만들기
	char a[1010]; // 1000자리지만 넉넉하게
	char b[1010];
	int chk1 = 0; // 부호처리용 변수
	int chk2 = 0;

	std::cin >> a >> b; // a와 b를 이용해 두 수를 받는다


	// 부호처리 - 음수면 부호처리용 변수에 1 넣음
	if (a[0] == '-')
		chk1 = 1;
	if (b[0] == '-')
		chk2 = 1;


	// 아래 식들은 죄다 부호처리용 변수가 더해져있는데, 어짜피 0 더하면 그대로니까 관계 없어서 그냥 다 이렇게 썼다. 
	// 덧셈
	if (chk1 + chk2 == 0) { // 둘다 양수면 그대로 더함
		if (bigger(a + chk1, b + chk2) != 0) { // add 메소드를 사용하기 위해 크기비교 (큰놈이 앞으로 와야하니까), 같은경우도 꼭 확인!!
			add(a + chk1, b + chk2);
		}
		else {
			add(b + chk2, a + chk1);
		}

	}

	else if (chk1 + chk2 == 2) { // 둘다 음수면 더해서 부호 - 붙여줌
		if (bigger(a + chk1, b + chk2) != 0) { // add 메소드를 사용하기 위해 크기비교 (큰놈이 앞으로 와야하니까), 같은경우도 꼭 확인!!
			std::cout << '-';
			add(a + chk1, b + chk2);
		}
		else {
			std::cout << '-';
			add(b + chk2, a + chk1);
		}
	}

	else { // 둘 중 하나만 음수면
		if (chk1 == 1 && chk2 == 0) { // a가 음수면
			if (bigger(a + chk1, b + chk2) == 1) { // 절대값이 a가 더 크면
				std::cout << '-';
				subtract(a + chk1, b + chk2); // 음수부호 때리고 절대값a에서 b 빼줌
			}
			else { // 절대값이 같거나 b가 더 크면
				subtract(b + chk2, a + chk1); // b에서 절대값a 빼줌
			}
		}
		else if (chk1 == 0 && chk2 == 1) { // b가 음수면
			if (bigger(a + chk1, b + chk2) != 0) { // 절대값이 같거나 a가 더 크면
				subtract(a + chk1, b + chk2); // a에서 절대값b 빼줌
			}
			else { // 절대값이 b가 더 크면
				std::cout << '-';
				subtract(b + chk2, a + chk1); // 음수부호 때리고 절대값b에서 a 빼줌
			}
		}
	}


	// 뺄셈
	if (chk1 + chk2 == 0) { // 둘다 양수면
		if (bigger(a + chk1, b + chk2) != 0) { // 절대값이 같거나 a가 더 크면
			subtract(a + chk1, b + chk2); // a에서 b 빼줌
		}
		else { // 절대값이 b가 더 크면
			std::cout << '-';
			subtract(b + chk2, a + chk1); // 음수부호 때리고 b에서 a 빼줌
		}
	}

	else if (chk1 + chk2 == 2) { // 둘다 음수면
		if (bigger(a + chk1, b + chk2) == 1) { // 절대값이 a가 더 크면
			std::cout << '-';
			subtract(a + chk1, b + chk2); // 절대값b에서 절대값a 빼줌
		}
		else { // 절대값이 같거나 b가 더 크면
			subtract(b + chk2, a + chk1); // 음수부호 때리고 절대값a에서 절대값b 빼줌
		}
	}

	else {
		if (chk1 == 1 && chk2 == 0) { // a만 음수면
			if (bigger(a + chk1, b + chk2) != 0) { // add 메소드를 사용하기 위해 크기비교 (큰놈이 앞으로 와야하니까)
				std::cout << '-';
				add(a + chk1, b + chk2); // 음수부호 때리고 절대값a랑 b를 더해준다
			}
			else {
				std::cout << '-';
				add(b + chk2, a + chk1);
			}
		}
		else if (chk1 == 0 && chk2 == 1) { // b만 음수면
			if (bigger(a + chk1, b + chk2) != 0) { // add 메소드를 사용하기 위해 크기비교 (큰놈이 앞으로 와야하니까)
				add(a + chk1, b + chk2); // a랑 절대값b를 더해준다
			}
			else {
				add(b + chk2, a + chk1);
			}

		}
	}


	//곱셈
	if (chk1 + chk2 == 1 && a[0] != '0' && b[0] != '0') // a와 b 둘다 0이 아니고, 둘중 하나라도 음수면 곱해도 음수 (알고리즘은 제일 어려웠으면서 출력은 제일 간단해서 좋다)
		std::cout << '-';

	multiple(a + chk1, b + chk2); // 곱해준다

	return 0;
}

https://jaimemin.tistory.com/1552

 

백준 2338번 긴자리 계산 (C++)

문제 링크입니다: www.acmicpc.net/problem/2338 2338번: 긴자리 계산 첫째 줄에 A+B, 둘째 줄에 A-B, 셋째 줄에 A×B를 출력한다. 각각을 출력할 때, 답이 0인 경우를 제외하고는 0으로 시작하게 해서는 안 된

jaimemin.tistory.com

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

// 앞에 불필요한 0을 제거
string getResultWithoutUnnecessaryZeros(string result)
{
    // 최초로 0이 아닌 인덱스를 찾는다
    int firstNonZeroIdx = result.size();

    for (int i = 0; i < result.size(); i++)
    {
        if (result[i] != '0')
        {
            firstNonZeroIdx = i;
            break;
        }
    }

    // 모든 자리가 0이라면 0을 반환
    if (firstNonZeroIdx == result.size())
    {
        return "0";
    }

    // 최초로 0이 아닌 자리부터의 숫자들을 반환
    return result.substr(firstNonZeroIdx);
}


// bigInteger 덧셈 함수
string add(string s1, string s2)
{
    // 덧셈의 결과 길이는 최소 s1과 s2 중 더 큰 숫자의 길이
    string result(max(s1.size(), s2.size()), '0');

    bool carry = false;

    // 끝에부터 더해 나감
    for (int i = 0; i < result.size(); i++)
    {
        int temp = carry;
        carry = false;

        if (i < s1.size())
        {
            temp += s1[s1.size() - i - 1] - '0';
        }

        if (i < s2.size())
        {
            temp += s2[s2.size() - i - 1] - '0';
        }

        if (temp >= 10)
        {
            carry = true;
            temp -= 10;
        }

        result[result.size() - i - 1] = temp + '0';
    }

    // 마지막에도 캐리가 있다면 맨 앞에 1 추가
    if (carry)
    {
        result.insert(result.begin(), '1');
    }

    return getResultWithoutUnnecessaryZeros(result);
}

// s1이 s2보다 큰 지 여부를 판별하는 함수
bool isFormerBiggerThanLatter(string s1, string s2)
{
    if (s1.size() != s2.size())
    {
        return s1.size() > s2.size();
    }

    for (int i = 0; i < s1.length(); i++)
    {
        if (s1[i] == s2[i])
        {
            continue;
        }
 
        return s1[i] > s2[i];
    }

    return false;
}


// bigInteger 뺄셈 함수 (부호는 판별 X)
string subtract(string s1, string s2)
{
    // 절댓값 기준 s1과 s2 중 더 큰 수로부터 더 작은 수를 빼는 함수이므로
    if (isFormerBiggerThanLatter(s1, s2) == false)
    {
        swap(s1, s2);
    }

    // s1과 s2를 거꾸로 뒤집는다
    reverse(s1.begin(), s1.end());
    reverse(s2.begin(), s2.end());

    // 더 큰 수로부터 더 작은 수를 빼므로 add 함수와 달리 result를 s1으로 초기화
    string result = s1;

    int carry = 0;

    for (int i = 0; i < result.size(); i++)
    {
        int tempCarry = carry;
        carry = 0;

        // carry가 존재한다면 s1[i]로부터 1 뺌
        int temp = (s1[i] - '0') - tempCarry;

        // 음수가 된다면 carry가 존재한다고 표시 후 10을 더해줌
        if (temp < 0)
        {
            carry = 1;
            temp += 10;
        }

        if (i < s2.size())
        {
            temp -= (s2[i] - '0');

            if (temp < 0)
            {
                carry = 1;
                temp += 10;
            }
        }

        result[i] = temp + '0';
    }

    // carry가 있다면 마지막 자리 숫자 1 빼줌
    if (carry)
    {
        int lastDigit = result[result.size() - 1];
        lastDigit--;

        result[result.size() - 1] = lastDigit + '0';
    }

    // 다시 뒤집어준 뒤
    reverse(result.begin(), result.end());

    return getResultWithoutUnnecessaryZeros(result);
}


//bigInteger 곱셈 구현
string multiply(string s1, string s2)
{
    string result = "0";

    // 곱셈 과정을 그대로 구현
    for (int i = 0; i < s2.size(); i++)
    {
        string line(s1);
        int carry = 0;

        for (int j = s1.size() - 1; j >= 0; j--)
        {
            int temp = carry;
            carry = 0;

            temp += (s1[j] - '0') * (s2[s2.size() - (i + 1)] - '0');

            if (temp >= 10)
            {
                carry = temp / 10;
                temp %= 10;
            }

            line[j] = temp + '0';
        }

        if (carry > 0)
        {
            line.insert(line.begin(), carry + '0');
        }

        // 곱셈 과정을 생각해보면 0을 뒤에 붙여주는 이유를 알 것입니다.
        line += string(i, '0');

        result = add(result, line);
    }

    return getResultWithoutUnnecessaryZeros(result);
}

int main(void)
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    string A, B;

    cin >> A >> B;

    int APositive = A[0] != '-';
    int BPositive = B[0] != '-';

    if (APositive && BPositive)
    {
        // 둘 다 양수
        // 덧셈
        cout << add(A, B) << "\n";

        // 뺄셈
        if (isFormerBiggerThanLatter(A, B) == false && A != B)
        {
            cout << "-";
        }

        cout << subtract(A, B) << "\n";

        // 곱셈
        cout << multiply(A, B) << "\n";
    }



    else if (APositive == false && BPositive == false)
    {
        // 둘 다 음수
        // 덧셈
        cout << "-" << add(A.substr(1), B.substr(1)) << "\n";

        // 뺄셈
        if (isFormerBiggerThanLatter(A.substr(1), B.substr(1)))
        {
            cout << "-";
        }

        cout << subtract(A.substr(1), B.substr(1)) << "\n";

        // 곱셈
        cout << multiply(A.substr(1), B.substr(1)) << "\n";
    }

    else if (APositive && BPositive == false)
    {
        // A 양수, B 음수
        // 덧셈
        string tempResult = subtract(A, B.substr(1));

        // 절댓값 기준 A가 B보다 크거나 연산결과가 0이라면 결과는 양수

        if (isFormerBiggerThanLatter(A, B.substr(1)) || tempResult == "0")
        {
            cout << tempResult << "\n";
        }

        else
        {
            cout << "-" << tempResult << "\n";
        }

        // 뺄셈
        cout << add(A, B.substr(1)) << "\n";

        // 곱셈
        cout << "-" << multiply(A, B.substr(1)) << "\n";
    }



    else if (APositive == false && BPositive)
    {
        // A 음수, B 양수
        // 덧셈
        string tempResult = subtract(A.substr(1), B);

        // 절댓값 기준 A가 B보다 크거나 연산결과가 0이 아니라면 결과는 음수
        if (isFormerBiggerThanLatter(A.substr(1), B) && tempResult != "0")
        {
            cout << "-" << tempResult << "\n";
        }

        else
        {
            cout << tempResult << "\n";
        }

        // 뺄셈
        cout << "-" << add(A.substr(1), B) << "\n";

        // 곱셈
        cout << "-" << multiply(A.substr(1), B) << "\n";
    }

    return 0;
}

'C++ 문법' 카테고리의 다른 글

FVector::DotProduct 과 FVector::Dot 의 차이  (0) 2024.02.28
string 의 substr 함수  (0) 2024.01.04
디자인 패턴, 정적 변수(static)  (0) 2022.04.15
생성자와 소멸자, 헤더 파일, cpp 파일  (0) 2022.04.15
클래스  (0) 2022.04.15