이차 방정식 ( ax^2 + bx + c = 0 )의 모든 근을 찾는 프로그램을 C언어로 5가지 방법으로 구현해 보겠습니다. 이차 방정식의 근은 판별식 ( D = b^2 - 4ac )에 따라 결정됩니다:
- ( D > 0 ): 두 개의 서로 다른 실근
- ( D = 0 ): 하나의 실근 (중근)
- ( D < 0 ): 두 개의 복소근
아래는 각기 다른 접근법으로 구현한 코드입니다. 복소근의 경우, C언어에서는 복소수 처리를 위해 complex.h
헤더를 사용합니다.
1. 기본 판별식 사용
알고리즘 설명
- 판별식 D = b² - 4ac 계산
- D > 0: 두 개의 실근
- D = 0: 중근
- D < 0: 허근 계산
장단점
장점: 가장 직관적인 구현 방식
단점: 복소수 표현이 제한적
#include <stdio.h>
#include <math.h>
#include <complex.h>
void solveQuadratic(double a, double b, double c) {
double D = b*b - 4*a*c;
if (D > 0) {
double root1 = (-b + sqrt(D)) / (2*a);
double root2 = (-b - sqrt(D)) / (2*a);
printf("두 개의 실근: %.2f, %.2f\n", root1, root2);
} else if (D == 0) {
double root = -b / (2*a);
printf("하나의 실근: %.2f\n", root);
} else {
double complex root1 = (-b + csqrt(D)) / (2*a);
double complex root2 = (-b - csqrt(D)) / (2*a);
printf("두 개의 복소근: %.2f + %.2fi, %.2f + %.2fi\n",
creal(root1), cimag(root1), creal(root2), cimag(root2));
}
}
int main() {
double a, b, c;
printf("a, b, c를 입력하세요: ");
scanf("%lf %lf %lf", &a, &b, &c);
solveQuadratic(a, b, c);
return 0;
}
2. 포인터를 이용한 값 반환
구현 특징
- 결과 값을 포인터 매개변수로 반환
- 근의 개수 정보(nature) 포함
- 함수 반환 값 없이 void 사용
주의사항
- 호출 전 포인터 메모리 할당 필요
- nature 값 해석: 0(허근), 1(중근), 2(두 실근)
#include <stdio.h>
#include <math.h>
#include <complex.h>
typedef void (*RootPrinter)(double complex, double complex, int);
void printRealRoots(double complex r1, double complex r2, int numRoots) {
if (numRoots == 1) {
printf("하나의 실근: %.2f\n", creal(r1));
} else {
printf("두 개의 실근: %.2f, %.2f\n", creal(r1), creal(r2));
}
}
void printComplexRoots(double complex r1, double complex r2, int numRoots) {
printf("두 개의 복소근: %.2f + %.2fi, %.2f + %.2fi\n",
creal(r1), cimag(r1), creal(r2), cimag(r2));
}
void solveQuadratic(double a, double b, double c, RootPrinter printer) {
double D = b*b - 4*a*c;
double complex root1, root2;
int numRoots;
if (D > 0) {
root1 = (-b + sqrt(D)) / (2*a);
root2 = (-b - sqrt(D)) / (2*a);
numRoots = 2;
} else if (D == 0) {
root1 = -b / (2*a);
root2 = root1;
numRoots = 1;
} else {
root1 = (-b + csqrt(D)) / (2*a);
root2 = (-b - csqrt(D)) / (2*a);
numRoots = 2;
}
printer(root1, root2, numRoots);
}
int main() {
double a, b, c;
printf("a, b, c를 입력하세요: ");
scanf("%lf %lf %lf", &a, &b, &c);
double D = b*b - 4*a*c;
if (D >= 0) {
solveQuadratic(a, b, c, printRealRoots);
} else {
solveQuadratic(a, b, c, printComplexRoots);
}
return 0;
}
3. 구조체 사용
구조체 설계
- Complex: 복소수 표현 (실수부, 허수부)
- Roots: 두 근과 근의 종류 저장
- 자료 캡슐화로 코드 안정성 향상
#include <stdio.h>
#include <math.h>
#include <complex.h>
typedef struct {
double complex root1;
double complex root2;
int numRoots;
} Roots;
Roots solveQuadratic(double a, double b, double c) {
Roots r;
double D = b*b - 4*a*c;
if (D > 0) {
r.root1 = (-b + sqrt(D)) / (2*a);
r.root2 = (-b - sqrt(D)) / (2*a);
r.numRoots = 2;
} else if (D == 0) {
r.root1 = -b / (2*a);
r.root2 = r.root1;
r.numRoots = 1;
} else {
r.root1 = (-b + csqrt(D)) / (2*a);
r.root2 = (-b - csqrt(D)) / (2*a);
r.numRoots = 2;
}
return r;
}
int main() {
double a, b, c;
printf("a, b, c를 입력하세요: ");
scanf("%lf %lf %lf", &a, &b, &c);
Roots roots = solveQuadratic(a, b, c);
if (roots.numRoots == 1) {
printf("하나의 실근: %.2f\n", creal(roots.root1));
} else if (cimag(roots.root1) == 0) {
printf("두 개의 실근: %.2f, %.2f\n", creal(roots.root1), creal(roots.root2));
} else {
printf("두 개의 복소근: %.2f + %.2fi, %.2f + %.2fi\n",
creal(roots.root1), cimag(roots.root1),
creal(roots.root2), cimag(roots.root2));
}
return 0;
}
4. 재귀 함수 활용
재귀적 설계
- 이차 방정식의 근과 계수의 관계를 활용한 재귀적 방법입니다.
- 이 방법은 교육적 목적에 더 적합하며, 실제로는 비효율적입니다.
#include <stdio.h>
#include <math.h>
#include <complex.h>
double findRoot(double a, double b, double c, double x) {
return a*x*x + b*x + c;
}
double findRootRecursive(double a, double b, double c,
double low, double high, double epsilon) {
double mid = (low + high) / 2;
double f_mid = findRoot(a, b, c, mid);
if (fabs(f_mid) < epsilon) {
return mid;
} else if (f_mid > 0) {
return findRootRecursive(a, b, c, low, mid, epsilon);
} else {
return findRootRecursive(a, b, c, mid, high, epsilon);
}
}
int main() {
double a, b, c;
printf("a, b, c를 입력하세요: ");
scanf("%lf %lf %lf", &a, &b, &c);
double D = b*b - 4*a*c;
if (D > 0) {
double root1 = findRootRecursive(a, b, c, -1000, 0, 0.0001);
double root2 = findRootRecursive(a, b, c, 0, 1000, 0.0001);
printf("두 개의 실근: %.2f, %.2f\n", root1, root2);
} else if (D == 0) {
double root = findRootRecursive(a, b, c, -1000, 1000, 0.0001);
printf("하나의 실근: %.2f\n", root);
} else {
printf("복소근은 이 방법으로 찾을 수 없습니다.\n");
}
return 0;
}
5. 배열을 통한 근 저장
근을 배열에 저장하여 반환하는 방식입니다.
#include <stdio.h>
#include <math.h>
#include <complex.h>
void solveQuadratic(double a, double b, double c,
double complex roots[2], int *numRoots) {
double D = b*b - 4*a*c;
if (D > 0) {
roots[0] = (-b + sqrt(D)) / (2*a);
roots[1] = (-b - sqrt(D)) / (2*a);
*numRoots = 2;
} else if (D == 0) {
roots[0] = -b / (2*a);
roots[1] = roots[0];
*numRoots = 1;
} else {
roots[0] = (-b + csqrt(D)) / (2*a);
roots[1] = (-b - csqrt(D)) / (2*a);
*numRoots = 2;
}
}
int main() {
double a, b, c;
double complex roots[2];
int numRoots;
printf("a, b, c를 입력하세요: ");
scanf("%lf %lf %lf", &a, &b, &c);
solveQuadratic(a, b, c, roots, &numRoots);
if (numRoots == 1) {
printf("하나의 실근: %.2f\n", creal(roots[0]));
} else if (cimag(roots[0]) == 0) {
printf("두 개의 실근: %.2f, %.2f\n", creal(roots[0]), creal(roots[1]));
} else {
printf("두 개의 복소근: %.2f + %.2fi, %.2f + %.2fi\n",
creal(roots[0]), cimag(roots[0]), creal(roots[1]), cimag(roots[1]));
}
return 0;
}
댓글
댓글 쓰기