flex-bison-in-action/analyzers/polynomials/poly_calc/poly_calc.c

180 lines
5.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "poly_calc.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// Возведение полинома в целую степень
Polynomial deg_poly(Polynomial *p, int degree) {
Polynomial result; init_polynomial(&result);
Polynomial temp = copy_poly(p);
for (int i = 1; i < degree; i++) {
Polynomial new_result = mul_polynomials(&temp, p);
free_polynomial(&temp);
temp = new_result;
}
result = temp;
return result;
}
// Возвращает копию полинома
Polynomial copy_poly(Polynomial *p) {
Polynomial result; init_polynomial(&result);
for (int i = 0; i < p->size; ++i) {
add_term(&result, p->terms[i].coefficient, p->terms[i].exponent);
}
return result;
}
Polynomial mul_polynomials(Polynomial *p1, Polynomial *p2) {
Polynomial result; init_polynomial(&result);
for (int i = 0; i < p1->size; ++i) {
for (int j = 0; j < p2->size; ++j) {
Term t1 = p1->terms[i];
Term t2 = p2->terms[j];
// Результат перемножения двух слагаемых
Term res_t;
res_t.coefficient = t1.coefficient * t2.coefficient;
res_t.exponent = t1.exponent + t2.exponent;
// Прибавление полученного результата (слагаемого)
// к результирующему полиному
add_term_and_poly(&result, res_t);
}
}
return result;
}
Polynomial sub_polynomials(Polynomial *p1, Polynomial *p2) {
for (int i = 0; i < p2->size; ++i) {
p2->terms[i].coefficient *= -1;
}
return add_polynomials(p1, p2);
}
// Cложение полиномов
Polynomial add_polynomials(Polynomial *p1, Polynomial *p2) {
Polynomial result; init_polynomial(&result);
for (int i = 0; i < p1->size; ++i) {
add_term_and_poly(&result, p1->terms[i]);
}
for (int i = 0; i < p2->size; ++i) {
add_term_and_poly(&result, p2->terms[i]);
}
return result;
}
// Сложение одного слагаемого и полинома
void add_term_and_poly(Polynomial *p, Term term) {
Term* t = exist_incremental(p, term);
if (t) {
t->coefficient += term.coefficient;
} else {
add_term(p, term.coefficient, term.exponent);
}
}
// Например есть полином x+1 и терм (2,1)=2x, значит в полиноме есть
// incremental (увеличиваемое), т.е. есть к чему прибавить 2x
Term* exist_incremental(Polynomial *p, Term term) {
for (int i = 0; i < p->size; ++i) {
if (p->terms[i].exponent == term.exponent) {
return &p->terms[i];
}
}
return NULL;
}
// Инициализация полинома
void init_polynomial(Polynomial *p) {
p->size = 0;
p->capacity = 4;
p->terms = (Term *)malloc(p->capacity * sizeof(Term));
if (!p->terms) {
perror("Memory allocation failed");
exit(EXIT_FAILURE);
}
}
// Добавление слагаемого в полином
void add_term(Polynomial *p, int coeff, int exp) {
// Проверяем, нужно ли расширить массив
if (p->size >= p->capacity) {
p->capacity *= 2;
p->terms = (Term *)realloc(p->terms, p->capacity * sizeof(Term));
if (!p->terms) {
perror("Memory reallocation failed");
exit(EXIT_FAILURE);
}
}
// Добавляем слагаемое
p->terms[p->size].coefficient = coeff;
p->terms[p->size].exponent = exp;
p->size++;
}
// Сортировка слагаемых в полиноме по убыванию степени
void sort_polynomial(Polynomial *p) {
for (int i = 0; i < p->size - 1; i++) {
for (int j = 0; j < p->size - i - 1; j++) {
if (p->terms[j].exponent < p->terms[j + 1].exponent) {
// Обмен слагаемых
Term temp = p->terms[j];
p->terms[j] = p->terms[j + 1];
p->terms[j + 1] = temp;
}
}
}
}
// Освобождение памяти, занятой полиномом
void free_polynomial(Polynomial *p) {
free(p->terms);
p->terms = NULL;
p->size = 0;
p->capacity = 0;
}
// Печать полинома
void print_polynomial(Polynomial *p, char letter) {
if (p->size == 0) {
printf("0\n");
return;
}
for (int i = 0; i < p->size; i++) {
Term term = p->terms[i];
if (term.coefficient == 0) {
continue;
}
// Печать знака (не печатаем '+' перед первым слагаемым)
if (i != 0 || term.coefficient < 0) {
printf("%c", term.coefficient > 0 ? '+' : '-');
}
// Печать коэффициента (если не 1/-1 или если степень 0)
if (abs(term.coefficient) != 1 || term.exponent == 0) {
printf("%d", abs(term.coefficient));
} else if (term.coefficient == -1 && term.exponent != 0) {
printf("-"); // Специальный случай для -x^n
}
// Печать переменной
if (term.exponent > 0) {
printf("%c", letter);
// Печать степени только если она больше 1
if (term.exponent > 1) {
printf("^%d", term.exponent);
}
}
}
printf("\n");
}