Полиномиальный наибольший общий делитель C++

Вот моя попытка реализовать программу, которая находит НОД двух многочленов. Я понимаю, что есть проблема в методе деления. Цикл while, уменьшающий степень результирующего многочлена в division(), в некоторых случаях уходит в «бесконечность», и я не могу понять, в каких именно.

Есть какие-нибудь подсказки, что здесь не так?

#include<iostream>
#include<stdlib.h>



using namespace std;

//polynomial------------------------------
struct polynomial {
    float *coeff;
    int degree;
};

/*function declaration */
int get_data(polynomial *P); 
int display(polynomial *P);
int division(polynomial *P, polynomial *Q, polynomial *H, polynomial *R);
int polcpy(polynomial *p, polynomial *q);
void GCDPol(polynomial *P,polynomial *Q, polynomial *R);

//GCD of two polynomials------------------
void GCDpol(polynomial *P,polynomial *Q, polynomial *R) {
    polynomial *res, *v;
    res = (polynomial *) calloc(1,sizeof(polynomial));  
    v = (polynomial *) calloc(1,sizeof(polynomial));  
    while(1) {
        division(P, Q, v, R);
        if(R->degree==0 && R->coeff[0]==0)
            break;
        else
            polcpy(P,Q);
            polcpy(Q,R);
    }
    polcpy(R,Q);
    free(res);
    free(v);
}

//pol copy--------------------------------
int polcpy(polynomial *p, polynomial *q) {
    p->degree=q->degree;
    p->coeff = new float[p->degree + 1];
    for (int i=0; i<=p->degree; i++) 
        p->coeff[i]=q->coeff[i];
    return 0;
}

//division--------------------------------
int division(polynomial *P, polynomial *Q, polynomial *H, polynomial *R) {
    float u;
    int x;
    polynomial *nh, *nr;
    nh = (polynomial *) calloc(1,sizeof(polynomial));
    nr = (polynomial *) calloc(1,sizeof(polynomial));

    /*Euclidian Long Division*/
    polcpy(nr, P);  
    nh->degree = P->degree - Q->degree;
    nh->coeff = new float[nh->degree + 1];
    for (int i=nh->degree; i>=0; i--)  {
        nh->coeff[i] = nr->coeff[nr->degree] / Q->coeff[Q->degree];
        for (int j=i; j <= nr->degree; j++) {
            u = nh->coeff[i] * Q->coeff[j-i];
            nr->coeff[j] = nr->coeff[j] - u;
        }
        if (nr->degree > 0)  
            nr->degree--;
    }

    /*Quotient*/
    polcpy(H, nh);  
    /*Remainder*/   
    polcpy(R, nr);
    while(R->coeff[R->degree] == 0) {
        R->degree--;
    }   
    free(nh); 
    free(nr);
    return 0;
}

//display-------------------------------
int display(polynomial *P) {
    int i, j;
    for (i = P->degree; i >= 0; i--) {
        cout << P->coeff[i] << "x^" << i;
        if ((i - 1) != -1)
            cout << "+";
    }
    cout << "\n";
    return 0;
}

//get_data------------------------------
int get_data(polynomial *P) {
    cout << "Enter Degree Of Polynomial:";
    cin >> P->degree;
    P->coeff = new float[P->degree + 1];
    for (int i = P->degree; i >= 0; i--) {
        cout << "Enter coefficient of x^" << i << ":";
        cin >> P->coeff[i];
    }
    return 0;
}


int main() {
    polynomial *P, *Q, *R, *H;
    P = (polynomial *) calloc(1,sizeof(polynomial));
    Q = (polynomial *) calloc(1,sizeof(polynomial));
    R = (polynomial *) calloc(1,sizeof(polynomial));
    H = (polynomial *) calloc(1,sizeof(polynomial));
    cout<<"GDC\n";
    get_data(P);
    get_data(Q);
    cout << "Polynomial1:";
    display(P);
    cout << "Polynomial2:";
    display(Q);
    GCDpol(P,Q,R);
    display(R);
    free(R);
    free(P);
    free(Q);
    free(H);
    return 0;
}

person noob_1    schedule 08.04.2015    source источник
comment
Было бы очень полезно, если бы вы точно указали, что происходит не так (и где, если вы знаете), а не давали расплывчатое описание. Кроме того, примеры входных данных, с которыми что-то не так.   -  person    schedule 10.04.2015


Ответы (3)


Представляется вероятным, что линия

if(R->degree==0 && R->coeff[0]==0)
        break;

это то, что сломано. Ваши коэффициенты являются плавающими. Поскольку компьютеры (к сожалению) конечны, в ваших вычислениях с плавающей запятой будут небольшие ошибки. Код выходит из цикла while только в том случае, если коэффициент точно равен 0. Кажется вероятным, что на некоторых входных данных, хотя он должен делить поровну, вы получите R->coeff[0] = 0.0000000001 или какое-то другое очень маленькое значение, которое не совсем равно 0.

Попробуйте проверить, находится ли абсолютное значение в пределах некоторого очень маленького допуска (например, 10^-10 или 10^-12). червей.

(Посмотрев на код более внимательно, вы сделаете точную проверку на равенство и в других местах — все это должно быть изменено на проверку абсолютного значения очень мало.)

person Titandrake    schedule 10.04.2015

while(R->coeff[R->degree] == 0) {
    R->degree--;
}

Это идет очень неправильно, если R является нулевым полиномом.

person Community    schedule 09.04.2015
comment
Кроме того, точное сравнение с float данными обычно является плохой идеей, хотя возможно здесь это допустимо или даже правильно. Но рассмотрите возможность обращения с достаточно малыми коэффициентами за нуль. - person ; 10.04.2015

Эта библиотека C++ реализует деление полиномов: а>

person Serg    schedule 20.12.2018