Metodo Ruffini per polinomi

di il
11 risposte

Metodo Ruffini per polinomi

Buongiorno,
avrei bisogno di un aiuto riguardante la creazione di un programma che scompone i polinomi con il metodo di ruffini.
grazie

11 Risposte

  • Re: Metodo Ruffini per polinomi

    Ciao, il problema mi sembra interessante!

    Hai ben chiara la "teoria" che c'è dietro dal punto di vista matematico? Da cosa partiresti per implementare il tutto?
  • Re: Metodo Ruffini per polinomi

    La teoria ce l'ho ben chiara...Il problema è applicarla nella codifica di c++.
    Pensavo di partire con la scomposizione in numeri primi ma poi non riesco.
    Mi servirebbe un grande aiuto.
    Grazie
  • Re: Metodo Ruffini per polinomi

    Potresti partire da una versione semplice, dove il termine di grado massimo =1 è poi andare di brute force per trovare i divisori. Altrimenti per semplificare una frazione devi applicare un algoritmo del massimo comune divisore.
  • Re: Metodo Ruffini per polinomi

    Come detto da @Alexv, nel caso in cui il coefficiente del termine di grado massimo sia diverso da 1 le cose si complicano un po' e bisogna anche implementare alcune operazioni con le frazioni. Ovviamente sta a te decidere se implementare una versione semplificata o una valida per qualsiasi polinomio a coefficienti interi.

    IlBocia ha scritto:


    Pensavo di partire con la scomposizione in numeri primi ma poi non riesco.
    In realtà non penso che la scomposizione in numeri primi sia la strada migliore.
    Mi spiego meglio... quello che a te serve è determinare tutti i diversi divisori di un certo numero n. Per esempio per n=36 dovresti ricavare:

    1 - 36 - 2 -18 - 3 - 12 - 4 - 9 - 6

    invece andando di scomposizione in numeri primi ottieni

    36 = 2 * 2 * 3 * 3

    A questo punto poi ti toccherebbe associare i vari fattori primi tra loro (mediante combinazioni semplici) al fine di ottenere l'elenco postato in precedenza.

    Quindi per iniziare il mio consiglio è quello di implementare una funzione che ricevuto il parametro 36 restituisca l'array

    1 - 36 - 2 -18 - 3 - 12 - 4 - 9 - 6

    Riflettici e comincia a postare un tuo tentativo, poi se serve ti aiutiamo.


    P.S.
    Visto che la teoria ce l'hai ben chiara, perché non ci illustri l'algoritmo complessivo a cui hai pensato?!
  • Re: Metodo Ruffini per polinomi

    Dal momento che il problema mi sembrava interessante, ho provato ad implementare qualcosa... ecco il codice:
    #include <iostream>
    #include <algorithm>
    #include <cstdint>
    #include <vector>
    
    using namespace std;
    
    int64_t mcd(int64_t a, int64_t b)
    {
        if(a < 0)
        {
            a = -a;
        }
        if(b < 0)
        {
            b = -b;
        }
        int64_t r;
        while(r = a % b)
        {
            a = b;
            b = r;
        }
        return b;
    }
    
    int64_t mcm(int64_t a, int64_t b)
    {
        if(a < 0)
        {
            a = -a;
        }
        if(b < 0)
        {
            b = -b;
        }
        return b / mcd(a, b) * a;
    }
    
    class frazione
    {
    private:
        int64_t num;
        int64_t den;
    
        void normalizza_frazione()
        {
            if(!num)
            {
                den = 1;
            }
            else
            {
                if(den < 0)
                {
                    num = -num;
                    den = -den;
                }
                int64_t MCD = mcd(num, den);
                num /= MCD;
                den /= MCD;
            }
        }
    
    public:
    
        frazione(const int64_t &_num = 0, const int64_t &_den = 1)
        {
            num = _num;
            den = _den;
            normalizza_frazione();
        }
    
        int64_t get_num() const
        {
            return num;
        }
    
        int64_t get_den() const
        {
            return den;
        }
    
        friend frazione operator -(const frazione &q)
        {
            return {-q.num, q.den};
        }
    
        friend frazione operator +(const frazione &q1, const frazione &q2)
        {
            frazione q3;
            q3.den = mcm(q1.den, q2.den);
            q3.num = q3.den / q1.den * q1.num + q3.den / q2.den * q2.num;
            q3.normalizza_frazione();
            return q3;
        }
    
        frazione& operator +=(const frazione &q)
        {
            return(*this = *this + q);
        }
    
        friend frazione operator *(const frazione &q1, const frazione &q2)
        {
            frazione q3(q1.num, q2.den);
            frazione q4(q2.num, q1.den);
            q3.num = q3.num * q4.num;
            q3.den = q3.den * q4.den;
            return q3;
        }
    
        frazione& operator *=(const frazione &q)
        {
            return(*this = *this * q);
        }
    
        friend frazione potenza(const frazione &base, const unsigned int esponente)
        {
            frazione q(1);
            for(unsigned int i = 0; i < esponente; ++i)
            {
                q *= base;
            }
            return q;
        }
    
        friend bool operator ==(const frazione &q1, const frazione &q2)
        {
            return(q1.num == q2.num && q1.den == q2.den);
        }
    
        friend bool operator !=(const frazione &q1, const frazione &q2)
        {
            return(!(q1 == q2));
        }
    
        friend std::ostream& operator <<(std::ostream &out, const frazione &q)
        {
            out << q.num;
            if(q.den != 1)
            {
                out << "/" << q.den;
            }
            return out;
        }
    
        explicit operator bool() const
        {
            return num;
        }
    
    };
    
    int64_t raccogli_denominatore(vector<frazione> &coef)
    {
        int64_t MCM = 1;
        for(unsigned int i = 0; i < coef.size(); ++i)
        {
            if(coef[i].get_den() != 1)
            {
                MCM = mcm(MCM, coef[i].get_den());
            }
        }
        if(MCM != 1)
        {
            for(unsigned int i = 0; i < coef.size(); ++i)
            {
                coef[i] *= MCM;
            }
        }
        return MCM;
    }
    
    vector<unsigned int> cerca_divisori(int64_t n)
    {
        vector<unsigned int> v;
        if(n < 0)
        {
            n = -n;
        }
        for(unsigned int i = 1; i <= n / i; ++i)
        {
            if(!(n % i))
            {
                v.push_back(i);
                if(i != n / i)
                {
                    v.push_back(n / i);
                }
            }
        }
        return v;
    }
    
    vector<frazione> definisci_possibili_radici(const vector<unsigned int> &div_coef_0, const vector<unsigned int> &div_coef_max)
    {
        vector<unsigned int> u;
        vector<frazione> v;
        for(unsigned int i = 0; i < div_coef_0.size(); ++i)
        {
            for(unsigned int j = 0; j < div_coef_max.size(); ++j)
            {
                u.push_back(div_coef_max[1] / div_coef_max[j] * div_coef_0[i]);
            }
        }
        sort(u.begin(), u.end());
        u.erase(unique(u.begin(), u.end()), u.end());
        for(unsigned int i = 0; i < u.size(); ++i)
        {
            v.push_back({u[i], div_coef_max[1]});
            v.push_back(-v.back());
        }
        return v;
    }
    
    frazione valuta_polinomio(const vector<frazione> &coef, const frazione &x)
    {
        frazione q;
        for(unsigned int i = 0; i < coef.size(); ++i)
        {
            q += coef[i] * potenza(x, coef.size() - 1 - i);
        }
        return q;
    }
    
    void stampa_polinomio(const vector<frazione> &coef)
    {
        cout << "(";
        unsigned int grado = coef.size() - 1;
        for(unsigned int i = 0; i <= grado; ++i)
        {
            if(coef[i])
            {
                cout << " ";
                if(i && coef[i].get_num() > 0)
                {
                    cout << "+";
                }
                if(i == grado || coef[i] != 1 && coef[i] != -1)
                {
                    cout << coef[i];
                }
                if(i < grado)
                {
                    if(coef[i] == -1)
                    {
                        cout << "-";
                    }
                    cout << "X";
                    if(grado - i > 1)
                    {
                        cout << "^" << grado - i;
                    }
                }
            }
        }
        cout << " )";
    }
    
    int main()
    {
        //INSERIRE I COEFFICIENTI DEL POLINOMIO COMPLETO ORDINATO SECONDO LE POTENZE DECRESCENTI.
        //SI POSSONO INSERIRE ANCHE FRAZIONI.
        vector<frazione> coef = {4, 0, -3, 5, -6};
        //vector<frazione> coef = {2, 5, -5, -5, 3};
        //vector<frazione> coef = {{1, 12}, {-3, 4}, {13, 6}, -2};
        //vector<frazione> coef = {1, -7, 4, 5, -2};
    
        if(coef.front() && coef.back())
        {
            stampa_polinomio(coef);
            cout << " = ";
            int64_t MCM = raccogli_denominatore(coef);
            vector<unsigned int> div_coef_0 = cerca_divisori(coef.back().get_num());
            vector<unsigned int> div_coef_max = cerca_divisori(coef.front().get_num());
            vector<frazione> v = definisci_possibili_radici(div_coef_0, div_coef_max);
            if(MCM != 1)
            {
                cout << frazione(1, MCM) << " ";
                stampa_polinomio(coef);
                cout << " = ";
                cout << frazione(1, MCM) << " ";
            }
            for(unsigned int i = 0; i != v.size() && coef.size() > 2;)
            {
                for(i = 0; i < v.size(); ++i)
                {
                    if(!valuta_polinomio(coef, v[i]))
                    {
                        coef.pop_back();
                        for(unsigned int j = 1; j < coef.size(); ++j)
                        {
                            coef[j] += coef[j - 1] * v[i];
                        }
                        stampa_polinomio({1, -v[i]});
                        break;
                    }
                }
            }
            stampa_polinomio(coef);
            cout << endl;
        }
    }
    Il programma scompone il polinomio inserito fin quando possibile. L'input, che va inserito nella prima riga del main(), consiste nei coefficienti (che possono essere anche frazioni) di un polinomio completo ordinato secondo le potenze decrescenti.
    Di seguito alcuni esempi:

    INPUT --> {4, 0, -3, 5, -6}
    ( 4X^4 -3X^2 +5X -6 ) = ( X -1 )( X +3/2 )( 4X^2 -2X +4 )
    
    Process returned 0 (0x0)   execution time : 0.339 s
    Press any key to continue.
    INPUT --> {{1, 12}, {-3, 4}, {13, 6}, -2}
    ( 1/12X^3 -3/4X^2 +13/6X -2 ) = 1/12 ( X^3 -9X^2 +26X -24 ) = 1/12 ( X -2 )( X -3 )( X -4)
    
    Process returned 0 (0x0)   execution time : 0.030 s
    Press any key to continue.
    INPUT --> {1, -7, 4, 5, -2} (polinomio irriducibile)
    ( X^4 -7X^3 +4X^2 +5X -2 ) = ( X^4 -7X^3 +4X^2 +5X -2 )
    
    Process returned 0 (0x0)   execution time : 0.018 s
    Press any key to continue.

    Se trovate qualche bug o qualche errore dal punto di vista dell'impostazione matematica, fatemi sapere.
  • Re: Metodo Ruffini per polinomi

    Alla fine insieme ad un mio amico sono riuscito a fare il metodo di ruffini con grado massimo 9

    #include <iostream>
    #include <string>
    #include <math.h>

    using namespace std;

    string eq;
    int values[10];
    int rsol[11][10];
    int count = 0;
    int maxn = 0;
    int done = 0;

    bool InputEq() {
    int pot = 0, nh = 1;
    string pots = "", h = "";
    getline(cin, eq);
    for (int i = 0; 100; i++) {
    if (eq == 'x' && eq[i+1] == '^') {
    pots = eq[i+2];
    pot = stoi(pots);
    if (h == "" || h == "+")
    values[pot] = 1;
    else if (h == "-")
    values[pot] = -1;
    else
    values[pot] = stoi(h);
    h = "";
    pots = "";
    i += 3;
    count++;
    }
    else if (eq == 'x'){
    i += 1;
    if (h == "" || h == "+")
    values[pot] = 1;
    else if (h == "-")
    values[pot] = -1;
    else
    values[1] = stoi(h);
    h = "";
    count++;
    }
    if (eq == '='){
    if (h == "")
    values[0] = 0;
    else
    values[0] = stoi(h);
    nh++;
    break;
    }
    if (eq != ' ')
    h += eq;
    }
    if (!nh)
    return true;
    else
    return false;
    }

    bool Ruffini() {
    int limit = rsol[maxn-done][done];
    if (limit < 0)
    limit *= -1;
    if (limit == 0) {
    rsol[0][done] = 0;
    for(int i = 1; i < maxn-done; i++)
    rsol[done+1] = rsol[done];
    done++;
    return true;
    }
    else
    for (int i = -limit; i <= limit; i++) {
    rsol[1][done+1] = rsol[1][done];
    for (int k = 2; k <= maxn-done; k++) {
    rsol[k][done+1] = rsol[k][done] + rsol[k-1][done+1] * i;
    }
    if (rsol[maxn-done][done+1] == 0) {
    rsol[0][done] = i;
    done++;
    return true;
    }
    }
    return false;
    }

    int main() {
    for (int i = 0; i < 12; i++)
    for (int j = 0; j < 11; j++)
    rsol[j] = 0;
    cout << "RUFFINI EQUATION SOLVER\n\n------------------------------------------------------------------------\n\nInput equation type: ax^(n)+bx^(n-1)+cx^(n-2)...+z=0 without spaces, max n must be < 10, thank you!\n\t> ";
    while (InputEq()) { }
    for (int i = 9; i >= 0; i--) {
    if (values != 0) {
    maxn = i;
    break;
    }
    }
    for (int i = 0; i <= maxn; i++) {
    rsol[i+1][0] = values[maxn-i];
    }
    maxn++;
    while(Ruffini()) {}

    // SOLUTION OUTPUT

    cout << "\n\nSolution:\n\t> ";
    for (int i = 0; i < done; i++) {
    cout << "(x";
    if (rsol[0] < 0)
    cout << "+";
    cout << -rsol[0][i] << ")";
    if (i < done - 1)
    cout << " * ";
    }
    if (done == maxn - 1) {
    if (rsol[1][done] != 1)
    cout << " * " << rsol[1][done];
    }
    else {
    cout << " * (";
    for (int i = 1; i < maxn - done - 1; i++) {
    if (rsol[i][done] != 1 and rsol[i][done] != 0)
    cout << rsol[i][done];
    if (rsol[i][done] != 0)
    cout << "x^" << maxn-done-i << " + ";
    }
    if (rsol[maxn-done-1][done] != 0)
    if (rsol[maxn-done-1][done] != 1)
    cout << rsol[maxn-done-1][done];
    cout << "x";
    if (rsol[maxn-done][done] >= 0)
    cout << " +";
    cout << rsol[maxn-done][done] << ")";
    }

    }
  • Re: Metodo Ruffini per polinomi

    IlBocia ha scritto:


    Alla fine insieme ad un mio amico sono riuscito a fare il metodo di ruffini con grado massimo 9
    Posta il codice utilizzando i TAG "code" altrimenti non si capisce nulla e non posso testarlo.
  • Re: Metodo Ruffini per polinomi

    Nippolo ha scritto:


    Dal momento che il problema mi sembrava interessante
    Li hai fatti i problemi della foobar di Google? Se vuoi ho ancora un invito, te lo mando in privato
    Sono in Java o Python , però
  • Re: Metodo Ruffini per polinomi

    Weierstrass ha scritto:


    Li hai fatti i problemi della foobar di Google? Se vuoi ho ancora un invito, te lo mando in privato
    Sono in Java o Python , però
    Premetto che ho dovuto fare qualche ricerca su internet per capire di cosa stessi parlando! Beh, che dire... certo che alla Silicon Valley le pensano proprio tutte!

    Ti ringrazio tanto per l'invito, ma proprio non conosco i linguaggi richiesti, ma solo le basi del C/C++ (in pratica mi sono avvicinato all'informatica grazie ad un esame (peraltro a scelta) di fondamenti all'università; da quel momento mi sono molto appassionato alla programmazione, che ho poi approfondito un po' da autodidatta quel poco che basta da poterla utilizzare come passatempo ed esercizio di logica).
    Inoltre, anche se ultimamente l'idea di lasciare il Draghistan non mi sembra più così peregrina, non potrei mai accettare il compromesso morale di lavorare per google... anche se in effetti potrebbe essere un'opportunità per sabotarli dall'interno!

    Quindi, scherzi a parte, non me la sento di farti sprecare l'invito, però se vuoi condividere qualche sfida di google interessante mi fa piacere!
  • Re: Metodo Ruffini per polinomi

    Eccolo
    #include <iostream>
    #include <string>
    #include <math.h>
    
    using namespace std;
    
    string eq;
    int values[10];
    int rsol[11][10];
    int count = 0;
    int maxn = 0;
    int done = 0;
    
    bool InputEq() {
    int pot = 0, nh = 1;
    string pots = "", h = "";
    getline(cin, eq);
    for (int i = 0; 100; i++) {
    if (eq == 'x' && eq[i+1] == '^') {
    pots = eq[i+2];
    pot = stoi(pots);
    if (h == "" || h == "+")
    values[pot] = 1;
    else if (h == "-")
    values[pot] = -1;
    else
    values[pot] = stoi(h);
    h = "";
    pots = "";
    i += 3;
    count++;
    }
    else if (eq == 'x'){
    i += 1;
    if (h == "" || h == "+")
    values[pot] = 1;
    else if (h == "-")
    values[pot] = -1;
    else
    values[1] = stoi(h);
    h = "";
    count++;
    }
    if (eq == '='){
    if (h == "")
    values[0] = 0;
    else
    values[0] = stoi(h);
    nh++;
    break;
    }
    if (eq != ' ')
    h += eq;
    }
    if (!nh)
    return true;
    else
    return false;
    }
    
    bool Ruffini() {
    int limit = rsol[maxn-done][done];
    if (limit < 0)
    limit *= -1;
    if (limit == 0) {
    rsol[0][done] = 0;
    for(int i = 1; i < maxn-done; i++)
    rsol[done+1] = rsol[done];
    done++;
    return true;
    }
    else
    for (int i = -limit; i <= limit; i++) {
    rsol[1][done+1] = rsol[1][done];
    for (int k = 2; k <= maxn-done; k++) {
    rsol[k][done+1] = rsol[k][done] + rsol[k-1][done+1] * i;
    }
    if (rsol[maxn-done][done+1] == 0) {
    rsol[0][done] = i;
    done++;
    return true;
    }
    }
    return false;
    }
    
    int main() {
    for (int i = 0; i < 12; i++)
    for (int j = 0; j < 11; j++)
    rsol[j] = 0;
    cout << "RUFFINI EQUATION SOLVER\n\n------------------------------------------------------------------------\n\nInput equation type: ax^(n)+bx^(n-1)+cx^(n-2)...+z=0 without spaces, max n must be < 10, thank you!\n\t> ";
    while (InputEq()) { }
    for (int i = 9; i >= 0; i--) {
    if (values != 0) {
    maxn = i;
    break;
    }
    }
    for (int i = 0; i <= maxn; i++) {
    rsol[i+1][0] = values[maxn-i];
    }
    maxn++;
    while(Ruffini()) {}
    
    // SOLUTION OUTPUT
    
    cout << "\n\nSolution:\n\t> ";
    for (int i = 0; i < done; i++) {
    cout << "(x";
    if (rsol[0] < 0)
    cout << "+";
    cout << -rsol[0][i] << ")";
    if (i < done - 1)
    cout << " * ";
    }
    if (done == maxn - 1) {
    if (rsol[1][done] != 1)
    cout << " * " << rsol[1][done];
    }
    else {
    cout << " * (";
    for (int i = 1; i < maxn - done - 1; i++) {
    if (rsol[i][done] != 1 and rsol[i][done] != 0)
    cout << rsol[i][done];
    if (rsol[i][done] != 0)
    cout << "x^" << maxn-done-i << " + ";
    }
    if (rsol[maxn-done-1][done] != 0)
    if (rsol[maxn-done-1][done] != 1)
    cout << rsol[maxn-done-1][done];
    cout << "x";
    if (rsol[maxn-done][done] >= 0)
    cout << " +";
    cout << rsol[maxn-done][done] << ")";
    }
    
    }
  • Re: Metodo Ruffini per polinomi

    IlBocia ha scritto:


    Eccolo
    Hai fatto copia e incolla dal post precedente, vero?

    Inserisci il codice originale, che qui mancano dei pezzi...

    Nippolo ha scritto:


    Se scrivi [ i ] (senza spazi) in un messaggio, esso non verrà visualizzato in quanto viene riconosciuto come il TAG iniziale per il corsivo...
Devi accedere o registrarti per scrivere nel forum
11 risposte