safe add and mult
parent
1a77b9cbd6
commit
ca6876771f
|
@ -2,6 +2,27 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
// Безопасное умножение с проверкой переполнения
|
||||||
|
int safe_mul(int a, int b) {
|
||||||
|
if (a > 0) {
|
||||||
|
if (b > 0 && a > INT_MAX / b) return 0; // Переполнение
|
||||||
|
if (b < 0 && b < INT_MIN / a) return 0; // Переполнение
|
||||||
|
} else if (a < 0) {
|
||||||
|
if (b > 0 && a < INT_MIN / b) return 0; // Переполнение
|
||||||
|
if (b < 0 && a < INT_MAX / b) return 0; // Переполнение
|
||||||
|
}
|
||||||
|
return a * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Безопасное сложение с проверкой переполнения
|
||||||
|
int safe_add(int a, int b) {
|
||||||
|
if ((b > 0 && a > INT_MAX - b) || (b < 0 && a < INT_MIN - b)) {
|
||||||
|
return 0; // Переполнение
|
||||||
|
}
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
// Возведение полинома в целую степень
|
// Возведение полинома в целую степень
|
||||||
Polynomial deg_poly(Polynomial *p, int degree) {
|
Polynomial deg_poly(Polynomial *p, int degree) {
|
||||||
|
@ -33,13 +54,26 @@ Polynomial mul_polynomials(Polynomial *p1, Polynomial *p2) {
|
||||||
Term t1 = p1->terms[i];
|
Term t1 = p1->terms[i];
|
||||||
Term t2 = p2->terms[j];
|
Term t2 = p2->terms[j];
|
||||||
|
|
||||||
// Результат перемножения двух слагаемых
|
// Безопасное умножение коэффициентов
|
||||||
Term res_t;
|
int safe_coeff = safe_mul(t1.coefficient, t2.coefficient);
|
||||||
res_t.coefficient = t1.coefficient * t2.coefficient;
|
if (t1.coefficient != 0 && t2.coefficient != 0 && safe_coeff == 0) {
|
||||||
res_t.exponent = t1.exponent + t2.exponent;
|
fprintf(stderr, "Multiplication overflow detected!\n");
|
||||||
|
free_polynomial(&result);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Безопасное сложение степеней
|
||||||
|
int safe_exp = safe_add(t1.exponent, t2.exponent);
|
||||||
|
if (safe_exp == 0 && (t1.exponent != 0 || t2.exponent != 0)) {
|
||||||
|
fprintf(stderr, "Exponent addition overflow detected!\n");
|
||||||
|
free_polynomial(&result);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Term res_t;
|
||||||
|
res_t.coefficient = safe_coeff;
|
||||||
|
res_t.exponent = safe_exp;
|
||||||
|
|
||||||
// Прибавление полученного результата (слагаемого)
|
|
||||||
// к результирующему полиному
|
|
||||||
add_term_and_poly(&result, res_t);
|
add_term_and_poly(&result, res_t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,12 +83,16 @@ Polynomial mul_polynomials(Polynomial *p1, Polynomial *p2) {
|
||||||
|
|
||||||
Polynomial sub_polynomials(Polynomial *p1, Polynomial *p2) {
|
Polynomial sub_polynomials(Polynomial *p1, Polynomial *p2) {
|
||||||
for (int i = 0; i < p2->size; ++i) {
|
for (int i = 0; i < p2->size; ++i) {
|
||||||
|
// Безопасное умножение на -1
|
||||||
|
if (p2->terms[i].coefficient == INT_MIN) {
|
||||||
|
fprintf(stderr, "Overflow when negating coefficient!\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
p2->terms[i].coefficient *= -1;
|
p2->terms[i].coefficient *= -1;
|
||||||
}
|
}
|
||||||
return add_polynomials(p1, p2);
|
return add_polynomials(p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cложение полиномов
|
|
||||||
Polynomial add_polynomials(Polynomial *p1, Polynomial *p2) {
|
Polynomial add_polynomials(Polynomial *p1, Polynomial *p2) {
|
||||||
Polynomial result; init_polynomial(&result);
|
Polynomial result; init_polynomial(&result);
|
||||||
|
|
||||||
|
@ -69,18 +107,23 @@ Polynomial add_polynomials(Polynomial *p1, Polynomial *p2) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сложение одного слагаемого и полинома
|
|
||||||
void add_term_and_poly(Polynomial *p, Term term) {
|
void add_term_and_poly(Polynomial *p, Term term) {
|
||||||
Term* t = exist_incremental(p, term);
|
Term* t = exist_incremental(p, term);
|
||||||
if (t) {
|
if (t) {
|
||||||
t->coefficient += term.coefficient;
|
// Безопасное сложение коэффициентов
|
||||||
|
int new_coeff = safe_add(t->coefficient, term.coefficient);
|
||||||
|
if (new_coeff == 0 && ((t->coefficient > 0 && term.coefficient > 0) ||
|
||||||
|
(t->coefficient < 0 && term.coefficient < 0))) {
|
||||||
|
fprintf(stderr, "Coefficient addition overflow detected!\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
t->coefficient = new_coeff;
|
||||||
} else {
|
} else {
|
||||||
add_term(p, term.coefficient, term.exponent);
|
add_term(p, term.coefficient, term.exponent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Например есть полином x+1 и терм (2,1)=2x, значит в полиноме есть
|
// Остальные функции остаются без изменений
|
||||||
// incremental (увеличиваемое), т.е. есть к чему прибавить 2x
|
|
||||||
Term* exist_incremental(Polynomial *p, Term term) {
|
Term* exist_incremental(Polynomial *p, Term term) {
|
||||||
for (int i = 0; i < p->size; ++i) {
|
for (int i = 0; i < p->size; ++i) {
|
||||||
if (p->terms[i].exponent == term.exponent) {
|
if (p->terms[i].exponent == term.exponent) {
|
||||||
|
@ -90,7 +133,6 @@ Term* exist_incremental(Polynomial *p, Term term) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Инициализация полинома
|
|
||||||
void init_polynomial(Polynomial *p) {
|
void init_polynomial(Polynomial *p) {
|
||||||
p->size = 0;
|
p->size = 0;
|
||||||
p->capacity = 4;
|
p->capacity = 4;
|
||||||
|
@ -101,9 +143,7 @@ void init_polynomial(Polynomial *p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Добавление слагаемого в полином
|
|
||||||
void add_term(Polynomial *p, int coeff, int exp) {
|
void add_term(Polynomial *p, int coeff, int exp) {
|
||||||
// Проверяем, нужно ли расширить массив
|
|
||||||
if (p->size >= p->capacity) {
|
if (p->size >= p->capacity) {
|
||||||
p->capacity *= 2;
|
p->capacity *= 2;
|
||||||
p->terms = (Term *)realloc(p->terms, p->capacity * sizeof(Term));
|
p->terms = (Term *)realloc(p->terms, p->capacity * sizeof(Term));
|
||||||
|
@ -113,18 +153,15 @@ void add_term(Polynomial *p, int coeff, int exp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Добавляем слагаемое
|
|
||||||
p->terms[p->size].coefficient = coeff;
|
p->terms[p->size].coefficient = coeff;
|
||||||
p->terms[p->size].exponent = exp;
|
p->terms[p->size].exponent = exp;
|
||||||
p->size++;
|
p->size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сортировка слагаемых в полиноме по убыванию степени
|
|
||||||
void sort_polynomial(Polynomial *p) {
|
void sort_polynomial(Polynomial *p) {
|
||||||
for (int i = 0; i < p->size - 1; i++) {
|
for (int i = 0; i < p->size - 1; i++) {
|
||||||
for (int j = 0; j < p->size - i - 1; j++) {
|
for (int j = 0; j < p->size - i - 1; j++) {
|
||||||
if (p->terms[j].exponent < p->terms[j + 1].exponent) {
|
if (p->terms[j].exponent < p->terms[j + 1].exponent) {
|
||||||
// Обмен слагаемых
|
|
||||||
Term temp = p->terms[j];
|
Term temp = p->terms[j];
|
||||||
p->terms[j] = p->terms[j + 1];
|
p->terms[j] = p->terms[j + 1];
|
||||||
p->terms[j + 1] = temp;
|
p->terms[j + 1] = temp;
|
||||||
|
@ -133,7 +170,6 @@ void sort_polynomial(Polynomial *p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Освобождение памяти, занятой полиномом
|
|
||||||
void free_polynomial(Polynomial *p) {
|
void free_polynomial(Polynomial *p) {
|
||||||
free(p->terms);
|
free(p->terms);
|
||||||
p->terms = NULL;
|
p->terms = NULL;
|
||||||
|
@ -141,7 +177,6 @@ void free_polynomial(Polynomial *p) {
|
||||||
p->capacity = 0;
|
p->capacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Печать полинома
|
|
||||||
void print_polynomial(Polynomial *p, char letter) {
|
void print_polynomial(Polynomial *p, char letter) {
|
||||||
if (p->size == 0) {
|
if (p->size == 0) {
|
||||||
printf("0\n");
|
printf("0\n");
|
||||||
|
@ -151,26 +186,20 @@ void print_polynomial(Polynomial *p, char letter) {
|
||||||
for (int i = 0; i < p->size; i++) {
|
for (int i = 0; i < p->size; i++) {
|
||||||
Term term = p->terms[i];
|
Term term = p->terms[i];
|
||||||
|
|
||||||
if (term.coefficient == 0) {
|
if (term.coefficient == 0) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Печать знака (не печатаем '+' перед первым слагаемым)
|
|
||||||
if (i != 0 || term.coefficient < 0) {
|
if (i != 0 || term.coefficient < 0) {
|
||||||
printf("%c", term.coefficient > 0 ? '+' : '-');
|
printf("%c", term.coefficient > 0 ? '+' : '-');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Печать коэффициента (если не 1/-1 или если степень 0)
|
|
||||||
if (abs(term.coefficient) != 1 || term.exponent == 0) {
|
if (abs(term.coefficient) != 1 || term.exponent == 0) {
|
||||||
printf("%d", abs(term.coefficient));
|
printf("%d", abs(term.coefficient));
|
||||||
} else if (term.coefficient == -1 && term.exponent != 0) {
|
} else if (term.coefficient == -1 && term.exponent != 0) {
|
||||||
printf("-"); // Специальный случай для -x^n
|
printf("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Печать переменной
|
|
||||||
if (term.exponent > 0) {
|
if (term.exponent > 0) {
|
||||||
printf("%c", letter);
|
printf("%c", letter);
|
||||||
// Печать степени только если она больше 1
|
|
||||||
if (term.exponent > 1) {
|
if (term.exponent > 1) {
|
||||||
printf("^%d", term.exponent);
|
printf("^%d", term.exponent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ extern FILE *yyin;
|
||||||
char allowed_variable = 0;
|
char allowed_variable = 0;
|
||||||
int current_line_number = 1;
|
int current_line_number = 1;
|
||||||
|
|
||||||
|
const char* INT_MAX_STR = "2147483646";
|
||||||
|
|
||||||
void yyerror(const char *s) {
|
void yyerror(const char *s) {
|
||||||
fprintf(stderr, "Error at line %i: %s\n", current_line_number, s);
|
fprintf(stderr, "Error at line %i: %s\n", current_line_number, s);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +19,16 @@ void yyerror(const char *s) {
|
||||||
";" { return SEMICOLON; }
|
";" { return SEMICOLON; }
|
||||||
"=" { return EQUAL; }
|
"=" { return EQUAL; }
|
||||||
[0-9]+ {
|
[0-9]+ {
|
||||||
|
size_t len = strlen(yytext);
|
||||||
|
if (len > strlen(INT_MAX_STR)) {
|
||||||
|
yyerror("Number too large (max 2147483646)");
|
||||||
|
exit(-1);
|
||||||
|
} else if (len == strlen(INT_MAX_STR)) {
|
||||||
|
if (strcmp(yytext, INT_MAX_STR) > 0) {
|
||||||
|
yyerror("Number too large (max 2147483646)");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
init_polynomial(&yylval.poly);
|
init_polynomial(&yylval.poly);
|
||||||
add_term(&yylval.poly, atoi(yytext), 0);
|
add_term(&yylval.poly, atoi(yytext), 0);
|
||||||
return NUMBER;
|
return NUMBER;
|
||||||
|
|
Loading…
Reference in New Issue