#include<iostream>
#include<cassert>
using namespace std;
struct FractionType
{
int num;
int den;
};
FractionType Add(FractionType a, FractionType b);// FractionType의 자료형을 가진 Add함수 인자는 FractionType의 자료형의 a<이름>(a안에 num, den존재)와 b(b안에 num, den 존재) a란 존재를 분수의 구성요소라 봐도됨
FractionType Sub(FractionType a, FractionType b);
FractionType Mpy(FractionType a, FractionType b);
FractionType Div(FractionType a, FractionType b);
void Reduction(FractionType& a);
void Reduction_NoPrint(FractionType& a);
int lcm(int m, int n);
int gcd(int m, int n);
int exit_Func();
int main()
{
FractionType a, b;
cout << "분자/분모를 차례대로 입력하시오(분모에 0넣으면 Error!)" << endl; // 기본적으로 분모가 0인 분수는 없다.
cout << "(음수인 분수는 분자에 음수를 입력해주세요 !! : "; //사용자가 입력시에 유의사항을 주었다. 음수 분수 입력하고싶으면 분자에다가 넣어라!
cin >> a.num >> a.den >> b.num >> b.den;
assert(a.den != 0 && b.den != 0); // 분수의 분모는 절때 0이 되어선 안된다. 절대로!! (메인함수에 넣어주면 굳이 다른 함수에서 0이 될 걱정이없음 분모가)
assert(a.den > 0 && b.den > 0); //입력받는 값이 음수인 분수일때 분자에 음수를 입력하는 조건이 있다.. 이를 위해 분모에 음수를 입력하면 바로 Debuging에러를 뜨게끔 해놓았다.
cout << "(" << a.num << "/" << a.den << ")+" << "(" <<b.num << "/" << b.den << ")=";
Reduction(Add(a, b));
cout << "(" << a.num << "/" << a.den << ")-" << "(" << b.num << "/" << b.den << ")=";
Reduction(Sub(a, b));
cout << "(" << a.num << "/" << a.den << ")*" << "(" << b.num << "/" << b.den << ")=";
Reduction(Mpy(a, b));
cout << "(" << a.num << "/" << a.den << ")/" << "(" << b.num << "/" << b.den << ")=";
Reduction(Div(a, b));
cout << endl;
return 0; // 종료
}
FractionType Add(FractionType a, FractionType b)
{
FractionType result;
Reduction_NoPrint(a);
Reduction_NoPrint(b);
result.den = lcm(a.den, b.den);
result.num = a.num*(result.den / a.den) + b.num*(result.den / b.den);
return result;
}
FractionType Sub(FractionType a, FractionType b)
{
FractionType result;
Reduction_NoPrint(a);
Reduction_NoPrint(b);
result.den = lcm(a.den, b.den);
result.num = a.num*(result.den / a.den) - b.num*(result.den / b.den);
return result;
}
FractionType Mpy(FractionType a, FractionType b)
{
FractionType result;
Reduction_NoPrint(a);
Reduction_NoPrint(b);
result.den = a.den*b.den;
result.num = a.num * b.num;
return result;
}
FractionType Div(FractionType a, FractionType b)
{
FractionType result;
Reduction_NoPrint(a);
Reduction_NoPrint(b);
result.den = a.den * b.num;
result.num = a.num * b.den;
if (result.den == 0)
{
cout << "분모엔 0이 못들어가지요.. 에러코드방출!" << endl;
assert(result.den != 0);
}
else
{
}
return result;
}
int lcm(int m, int n)
{
assert(m>0 && n>0);
int m1 = m / gcd(n, m); // 최소공배수 통분했을때 나오는 최대공약수 제외한 나머지 값
int n1 = n / gcd(n, m);
return gcd(n, m) * m1 * n1; // 최대 공약수 랑 통분했을 시 나오는 수들의 곱셈
}
int gcd(int n, int m) {
if (m > n) // 최대공약수 통분할때 뒷수가 앞수보다 크면 자리 배치 바꿈, 손으로 쓰는 통분은 앞수가 작아도 되는데 이 방법은 좀 상이해서 바꿔줘야한다.
{
int temp;
temp = n;
n = m;
m = temp; // 자리를 바꾸었다.
if (m == 0){ // 중첩 if문 만약 gcd에 0이들어오면<그럴일은 없겠지만...> 그냥 n이 최대공약수
return n;
}
else // 0이아니면
{
return gcd(m, n%m);
}
}
else
{
if (m == 0)
return n;
else
return gcd(m, n%m);
}
}
void Reduction(FractionType& a)
{
FractionType real_result;
if (a.num < 0 && a.den > 0) // Add함수와 Sub함수를 위한 조건(덧셈/뺄셈은 lcm<분모계산식>으로인해 분모는 양수가나올수 밖에없으니 만약 계산결과값이 음수라면 필자가 위에서 분자에 음수를 넣게끔 분자 계산방법이 짜져있을것이다.
{
int num;
num = -a.num;
gcd(num, a.den);
real_result.num = (a.num / gcd(num, a.den)); //음수인 함수를 약분하는 것이므로 num에 양수화를 시켰으면 다시 결과값은 되돌려서 주는게 맞다.
//만약 이방법으로 하기 싫다면 지역변수를 하나 선언하여 양수화된 값을 그 지역변수에 넣고 gcd를 돌린다.
real_result.den = (a.den / gcd(num, a.den));
}
else if (a.num > 0 && a.den < 0) // Mpy함수와 Div 함수를 위한 조건(곱셈/뺄셈은 굳이 통분해서 계산하는게 아니라 그냥 곱해서 약분만 하면되므로 결과가 음수가 나온 분수를 약분하려면 양수화시켜야하므로 사용
{
int den;
den = -a.den;
gcd(a.num, den);
real_result.num = -(a.num / gcd(a.num, den)); // 이것도 연산값은 음수이므로 통일 되게끔 분자에 음수를 넣어주겠다.
real_result.den = (a.den / gcd(a.num, den));
}
else if (a.num < 0 && a.den < 0) //분자 분모 둘다 음수일경우 둘다 양수화해서 gcd처리를 하고 어짜피 음수가 2개이면 양수이므로 양수화 시킨다.
{
int num, den;
num = -a.num;
den = -a.den;
gcd(num, den);
real_result.num = (num / gcd(num, den));
real_result.den = (den / gcd(num, den));
}
else
{ // 그냥 양수 분수를 약분하는 것이다.
gcd(a.num, a.den);
real_result.num = (a.num / gcd(a.num, a.den));
real_result.den = (a.den / gcd(a.num, a.den));
}
if (real_result.den == 1)
{
cout << real_result.num << endl; //약분 결과값의 분모가 1이면 정수출력
}
else if (real_result.den == 0)
{
exit_Func(); //약분 결과값의 분모가 0이면 프로그램 종료
}
else
{
cout << real_result.num << "/" <<real_result.den<< endl;
}
}
void Reduction_NoPrint(FractionType& a)
{
FractionType real_result;
if (a.num < 0 && a.den > 0) // Add함수와 Sub함수를 위한 조건(덧셈/뺄셈은 lcm<분모계산식>으로인해 분모는 양수가나올수 밖에없으니 만약 계산결과값이 음수라면 필자가 위에서 분자에 음수를 넣게끔 분자 계산방법이 짜져있을것이다.
{
int num;
num = -a.num;
gcd(num, a.den);
real_result.num = (a.num / gcd(num, a.den)); //음수인 함수를 약분하는 것이므로 num에 양수화를 시켰으면 다시 결과값은 되돌려서 주는게 맞다.
//만약 이방법으로 하기 싫다면 지역변수를 하나 선언하여 양수화된 값을 그 지역변수에 넣고 gcd를 돌린다.
real_result.den = (a.den / gcd(num, a.den));
}
else if (a.num > 0 && a.den < 0) // Mpy함수와 Div 함수를 위한 조건(곱셈/뺄셈은 굳이 통분해서 계산하는게 아니라 그냥 곱해서 약분만 하면되므로 결과가 음수가 나온 분수를 약분하려면 양수화시켜야하므로 사용
{
int den;
den = -a.den;
gcd(a.num, den);
real_result.num = -(a.num / gcd(a.num, den)); // 이것도 연산값은 음수이므로 통일 되게끔 분자에 음수를 넣어주겠다.
real_result.den = (a.den / gcd(a.num, den));
}
else if (a.num < 0 && a.den < 0) //분자 분모 둘다 음수일경우 둘다 양수화해서 gcd처리를 하고 어짜피 음수가 2개이면 양수이므로 양수화 시킨다.
{
int num, den;
num = -a.num;
den = -a.den;
gcd(num, den);
real_result.num = (num / gcd(num, den));
real_result.den = (den / gcd(num, den));
}
else
{ // 그냥 양수 분수를 약분하는 것이다.
gcd(a.num, a.den);
real_result.num = (a.num / gcd(a.num, a.den));
real_result.den = (a.den / gcd(a.num, a.den));
}
}
int exit_Func()
{
return 0;
}