stringcal

#ifndef _cal_h_

#define _cal_h_

#include<iostream>

#define outputlength 20

using namespace std;

class complex;

class real//利用了string不赋值为\0特性,某些情况下用debug会报错string越界

{

public:

    real() {};

    real(int level);//10^x

    real operator =(const real& that);

    real(const string& str);//wont check

    void get();

    void display(bool all = true)const;

    void clean(int x);// clean by 10^x

    void clear(int x);//front

    void zerooff();

    void addzero(int difflevel);

    const real chooseandrank(const real& that)const;//A

    const real choose(const real& that)const;//C

    const real factorial(bool single = true)const;//! and !!

    const real intdiv(const real& that, real& remain)const;

    const real gcd(const real& that)const;

    bool operator ==(const real& that)const;

    bool zero()const;//for +0 and -0

    bool positive()const;

    bool operator <=(const real& that)const;//abs,1<=1.0 is false but / works well,that's enough

    const real operator-()const { real a; a.number = number; a.point = point; a.sign = -sign; return a; }

    const real operator +(const real& that)const;

    const complex operator +(const complex& that)const;

    const real operator -(const real& that)const;

    const complex operator -(const complex& that)const;

    const real operator *(const real& that)const;

    const complex operator *(const complex& that)const;

    const real operator /(const real& that)const;

    const complex operator /(const complex& that)const;

    const real operator ^(const real& that)const;

    const real pow(const real& that)const;

    const real root(const real& that = real("2"))const;

    const real newtonroot(const real& that = real("2"), int level = -200)const;

    const real radian()const;//any degree->radian 0~2*pi

    const real cos()const;

    const real sin()const;

    const real tan()const;

    const real arccos()const;

    const real arcsin()const;

    const real arctan()const;

    const real cosh()const;

    const real sinh()const;

    const real tanh()const;

    const real exp()const;

    const real arccosh()const;

    const real arcsinh()const;

    const real arctanh()const;

    const real log()const;

    static short diff;// control / and ^ >=0

    static const real pi_2;

    friend class poly;

    friend class complex;

    friend class method;

private:

    string number;//0~9ascii reversed

    short sign = 1;

    int point = 0;

    int toint()const;

    bool show(bool all = true)const;

    static bool check(const string& that);

    void tailadd(const short x);//0~10 note is +

    void halfadjust();

    int intdivide2(bool complete = true);

    void sqrt(int level);

    void to2(string& str);

    static const real c_2_512;

};

short real::diff = 300;

const real real::c_2_512 = string("1340780792994259709957402499820584612747936582059239337772356144372176403007354697680") +

string("1874298166903427690031858186486050853753882811946569946433649006084096");//2^512

const real real::pi_2 = string("1.570796326794896619231321691639751442098584699687552910487472296153908203143104499") +

string("31401741267105853399107404325664115332354692230477529111586267970406") +

string("42405587251420513509692605527798223114744774651909822144054878329667230642378241");//pi/2

real::real(int level)

{

    if (level > 0)

    {

        for (; level > 0; level--)

        {

            number += '\0';

        }

        number += 1;

        return;

    }

    number += 1;

    if (level < 0)

    {

        point = -level;

        for (; level < 0; level++)

        {

            number += '\0';

        }

    }

}

real::real(const string& str)

{

    for (int i = str.size() - 1; i > 0; i--) {

        if (str[i] == '.') { point = number.size(); }

        else { number += str[i] - '0'; }

    }

    if (str[0] == '-') { sign = -1; }

    else { number += str[0] - '0'; }

}

bool real::check(const string& str)

{

    int l = str.size(), i = 0;

    if (str[0] == '-') { i++; }

    if ((str[i] == '0' && l != 1 && str[i + 1] != '.') || str.back() == '.' || str[i] == '.') { return false; }

    bool mark = true;

    for (; i < l; i++)

    {

        if (str[i] == '.' && mark) { mark = false; continue; }

        if (str[i] < '0' - 1 || str[i] > '9' + 1) { break; }

    }

    if (i == l) { return true; }

    return false;

}

void real::get()

{

    while (1)

    {

        string str;

        cin >> str;

        while (check(str) == false) { cout << "wrong input!" << endl; cin >> str; }

        *this = real(str);

        return;

    }

}

int real::toint()const

{

    int sum = 0, j = 1;

    for (char c : this->number)

    {

        sum += c * j; j *= 10;

    }

    return sum;

}

bool real::show(bool all)const

{

    if (sign == -1) { cout << "-"; }

    int i = number.size() - 1;

    if (all == false && i > outputlength)

    {

        while (i > 0 && number[i] == 0) { i--; }

        if (i) { cout << (short)number[i] << "."; }

        for (int j = i - 1; j > i - outputlength && j > -1; j--)

        {

            cout << (short)number[j];

        }

        i -= point;

        if (i > 0) { cout << "e+" << i; }

        else { cout << "e" << i; }

        return true;

    }

    for (; i > 0; i--) {

        cout << (short)number[i];

        if (point == i) { cout << "."; }

    }

    cout << (short)number[0];

    return false;

}

void real::display(bool all)const

{

    cout << "=>";

    if (show(0) && all) { cout << "\nexact value\n=>"; show(); }

    cout << endl;

}

void real::halfadjust()

{

    if (point)

    {

        int l = number.size();

        bool mark = number[0] > 4;

        for (int i = 1; i < l; i++)

        {

            number[i - 1] = number[i];

        }

        point--;

        number.pop_back();

        if (mark) { this->tailadd(1); }

    }

}

void real::clean(int x)

{

    if (x < 1)

    {

        x += point;

        if (x > 0) {

            point -= x;

            int l = number.size() - x;

            for (int i = 0; i < l; i++)

            {

                number[i] = number[i + x];

            }

            for (; x > 0; x--)

            {

                number.pop_back();

            }

        }

    }

    else

    {

        x = number.size() - point - x;

        if (x < 1) { number.clear(); number += '\0'; sign = 1; }

        else { this->clear(x); }

    }

}

void real::clear(int x)

{

    x = number.size() - x;

    if (x > 0)

    {

        if (x > point)

        {

            for (int i = point; i < x; i++)

            {

                number[i] = '\0';

            }

            x = number.size();

            for (int i = point; i < x; i++)

            {

                number[i - point] = number[i];

            }

            while (point > 0) { number.pop_back(); point--; }

            point = 0;

        }

        else

        {

            int l = number.size();

            for (int i = x; i < l; i++)

            {

                number[i - x] = number[i];

            }

            point -= x;

            while (x > 0) { number.pop_back(); x--; }

        }

    }

}

void real::zerooff()

{

    int i = 0;

    for (; i < point && number[i] == 0; i++);

    if (i)

    {

        point -= i; int l = number.size();

        for (int j = i; j < l; j++) {

            number[j - i] = number[j];

        }

        for (; i > 0; i--) { number.pop_back(); }

    }

}

void real::addzero(int difflevel)

{

    int l = difflevel - point;

    if (l > 0) {

        int p = number.size() - l;

        for (int i = 0; i < l; i++) { number += number[p + i]; }

        for (int i = p; i > -1; i--) { number[l + i] = number[i]; }

        for (int i = 0; i < l; i++) { number[i] = '\0'; }

        point = difflevel;

    }

}

void real::tailadd(const short x)

{

    number[0] += x;

    int l = number.size() - 1;

    for (int i = 0; i < l; i++)

    {

        if (number[i] > 9) { number[i + 1]++; number[i] -= 10; }

        else { break; }

    }

    if (number[l] > 9) { number[l] -= 10; number.push_back(1); }

}

int real::intdivide2(bool complete)

{

    if (number[0] % 2) { return 0; }

    int count = 0;

    do {

        for (int i = number.size(); i > -1; i--)

        {

            if (number[i] % 2 == 1) { number[i - 1] += 10; }

            number[i] /= 2;

        }

        count++;

    } while (number[0] % 2 == 0 && complete);

    while (number.back() == 0 && number.size() > 1) { number.pop_back(); }

    return count;

}

const real real::chooseandrank(const real& that)const

{

    if (point || that.point || sign == -1 || that.sign == -1 || number.back() == 0) { cout << "A wrong!"; exit(0); }

    real start = *this - that;

    if (start.sign == -1) { cout << "A wrong!"; exit(0); }

    start.tailadd(1);

    real result("1");

    while (start <= *this)

    {

        result = result * start;

        start.tailadd(1);

    }

    return result;

}

const real real::choose(const real& that)const

{

    if (point || that.point || sign == -1 || that.sign == -1 || number.back() == 0) { cout << "C wrong!"; exit(0); }

    if (*this - that <= that - real("1")) { return (*this).choose(*this - that); }

    real a("1"), b = (*this) - that, result("1"); b.tailadd(1);

    if (b.number.back() == 0 || b.sign == -1) { cout << "C wrong!"; exit(0); }

    if ((that.number.size() == 1 && (that.number[0] == 0)) || number == that.number) { return real("1"); }

    if (that.number.size() == 1 && that.number[0] == 1) { return *this; }

    short record = diff; diff = 0;

    while (a <= that)

    {

        result = result * b;

        result = result / a;

        a.tailadd(1); b.tailadd(1);

    }

    diff = record;

    return result;

}

const real real::factorial(bool single)const

{

    if (single) { return ((*this).factorial(0)) * ((*this - real("1")).factorial(0)); }

    if (point != 0 || sign == -1) { cout << " fac wrong!"; exit(0); }

    if (number.size() > 5) { cout << "fac too big!"; exit(0); }

    int l = this->toint();

    int* p1 = new int[1] {}; p1[0] = 1;

    short p2[5] = { 0 }; p2[0] = l % 2;

    int* p3;

    l /= 2; int l1 = 1; short l2 = 1; short start = 0;

    for (int i = 0; i < l; i++)

    {

        single = true;

        p2[0] += 1;

        for (short j = 0; j < l2; j++)

        {

            p2[j]++;

            if (p2[j] > 9) { p2[j] -= 10; }

            else { single = false; break; }

        }

        if (single) { p2[l2] = 1; l2++; }

        p3 = new int[l1 + l2] {};

        for (int j = start; j < l1; j++)

        {

            for (short k = 0; k < l2; k++)

            {

                p3[k + j] += p1[j] * p2[k];

            }

        }

        for (int j = 0; j < l1 + l2 - 1; j++)

        {

            p3[j + 1] += p3[j] / 10; p3[j] %= 10;

        }

        delete[]p1;

        if (p3[l1 + l2 - 1]) { l1 += l2; }

        else { l1 += l2 - 1; }

        p1 = p3;

        if (p1[start] == 0) { start++; }

    }

    real tmp;

    for (int i = 0; i < l1; i++)

    {

        tmp.number += p1[i];

    }

    delete[]p1;

    return tmp;

}

const real real::gcd(const real& that)const

{

    real a(*this), b(that), c("1");

    while (a.number.back() == 0) { a.number.pop_back(); a.point--; }

    while (b.number.back() == 0) { b.number.pop_back(); b.point--; }

    a.zerooff(); b.zerooff();

    a.sign = b.sign = 1; a.point = b.point = 0;

    while (c.zero() == false)

    {

        if (a <= b) { b = b - (a * b.intdiv(a, c)); }

        else { a = a - (b * a.intdiv(b, c)); }

    }

    if (a <= b) { return b; }

    else { return a; }

}

real real::operator =(const real& that)

{

    number = that.number;

    point = that.point;

    sign = that.sign;

    return *this;

}

const real real::operator +(const real& that) const

{

    int l1 = point, l2 = that.point;

    int l = l1 > l2 ? l1 : l2;

    int l3 = number.size() - l1, l4 = that.number.size() - l2;

    int k = l3 > l4 ? l3 : l4;

    short* p = new short[k + l + 1] {};

    for (int i = 0; i <= l1; i++) {

        p[l - i] += sign * (short)(number[l1 - i]);

    }

    for (int i = 0; i <= l2; i++) {

        p[l - i] += that.sign * that.number[l2 - i];

    }

    for (int i = 1; i < l3; i++)

    {

        p[l + i] += sign * number[l1 + i];

    }

    for (int i = 1; i < l4; i++)

    {

        p[l + i] += that.sign * that.number[l2 + i];

    }

    real result;

    result.sign = 1;

    for (int i = k + l; i > -1; i--)

    {

        if (p[i] > 0)

        {

            for (i = 0; i < k + l; i++)

            {

                if (p[i] < 0) { p[i] += 10; p[i + 1]--; }

            }

            break;

        }

        else if (p[i] < 0)

        {

            result.sign = -1;

            for (i = 0; i < k + l + 1; i++) { p[i] = -p[i]; }

            break;

        }

    }

    for (int i = 0; i < k + l; i++)

    {

        if (p[i] > 9) { p[i] -= 10; p[i + 1]++; }

        else if (p[i] < 0) { p[i] += 10; p[i + 1]--; }

    }

    k += l; result.point = l; l = 0;

    while (l < result.point && p[l] == 0) { l++; }

    while (k > result.point && p[k] == 0) { k--; }

    result.point -= l;

    for (; l < k + 1; l++)

    {

        result.number += p[l];

    }

    delete[]p;

    return result;

}

const real real::operator -(const real& that)const

{

    int l1 = point, l2 = that.point;

    int l = l1 > l2 ? l1 : l2;

    int l3 = number.size() - l1, l4 = that.number.size() - l2;

    int k = l3 > l4 ? l3 : l4;

    short* p = new short[k + l + 1] {};

    for (int i = 0; i <= l1; i++) {

        p[l - i] += sign * number[l1 - i];

    }

    for (int i = 0; i <= l2; i++) {

        p[l - i] -= that.sign * that.number[l2 - i];

    }

    for (int i = 1; i < l3; i++)

    {

        p[l + i] += sign * number[l1 + i];

    }

    for (int i = 1; i < l4; i++)

    {

        p[l + i] -= that.sign * that.number[l2 + i];

    }

    real result;

    result.sign = 1;

    for (int i = k + l; i > -1; i--)

    {

        if (p[i] > 0)

        {

            for (i = 0; i < k + l; i++)

            {

                if (p[i] < 0) { p[i] += 10; p[i + 1]--; }

            }

            break;

        }

        else if (p[i] < 0)

        {

            result.sign = -1;

            for (i = 0; i < k + l + 1; i++) { p[i] = -p[i]; }

            break;

        }

    }

    for (int i = 0; i < k + l; i++)

    {

        if (p[i] > 9) { p[i] -= 10; p[i + 1]++; }

        else if (p[i] < 0) { p[i] += 10; p[i + 1]--; }

    }

    k += l; result.point = l; l = 0;

    while (l < result.point && p[l] == 0) { l++; }

    while (k > result.point && p[k] == 0) { k--; }

    result.point -= l;

    for (; l < k + 1; l++)

    {

        result.number += p[l];

    }

    delete[]p;

    return result;

}

const real real::operator *(const real& that)const

{

    int l1 = number.size(), l2 = that.number.size();

    int* p = new int[l1 + l2] {};

    int start1 = 0, end1 = l1 - 1, start2 = 0, end2 = l2 - 1;

    while (number[start1] == 0) { start1++; }

    while (number[end1] == 0) { end1--; }

    while (that.number[start2] == 0) { start2++; }

    while (that.number[end2] == 0) { end2--; }

    for (int i = start1; i < end1 + 1; i++)

    {

        for (int j = start2; j < end2 + 1; j++)

        {

            p[i + j] += number[i] * that.number[j];

        }

    }

    for (int j = 0; j < l1 + l2 - 1; j++)

    {

        p[j + 1] += p[j] / 10; p[j] %= 10;

    }

    l1 += l2 - 1; l2 = point + that.point;

    while (l1 > l2 && p[l1] == 0) { l1--; }

    real result;

    result.point = l2; l2 = 0;

    while (l2 < result.point && p[l2] == 0) { l2++; }

    result.point -= l2;

    for (; l2 < l1 + 1; l2++)

    {

        result.number += p[l2];

    }

    delete[]p;

    result.sign = sign * that.sign;

    return result;

}

const real real::intdiv(const real& that, real& remain)const

{

    short d;

    if (point || that.point || (d = that.number.back()) == 0) { cout << "intdiv wrong!"; exit(0); }

    real result, div; short x;

    div.number = that.number;

    remain.number.clear(); remain.sign = 1;

    remain.number += '\0'; int k = that.number.size();

    for (int l = number.size(); l > -1; l--)

    {

        remain.number += '\0';

        for (int i = remain.number.size() - 1; i > 0; i--)

        {

            remain.number[i] = remain.number[i - 1];

        }

        if (l < 0) { remain.number[0] = '\0'; }

        else { remain.number[0] = number[l]; }

        if (remain.number.back() == 0) { remain.number.pop_back(); }

        if (div <= remain)

        {

            if (remain.number.size() == k) { x = remain.number.back() / d; }

            else { x = (10 * remain.number.back() + remain.number[remain.number.size() - 2]) / d; }

            real tmp; tmp.number += x;

            tmp = tmp * div;

            remain = remain - tmp;

            while (remain.sign == -1) { remain = remain + div; x--; }

            result.number += x;

        }

        else { result.number += '\0'; }

    }

    int l = result.number.size();

    for (int i = 0; i < l / 2; i++)

    {

        char c = result.number[l - i - 1];

        result.number[l - 1 - i] = result.number[i];

        result.number[i] = c;

    }

    while (result.number.empty() == false && result.number.back() == 0) { result.number.pop_back(); }

    if (that <= *this == false) { result.number += '\0'; }

    result.sign = sign * that.sign;

    remain.sign = sign;

    return result;

}

const real real::operator/(const real& that)const

{

    if (that.zero()) { cout << "?/0 wrong"; exit(0); }

    real result, current, div;

    int l;

    for (l = that.number.size() - 1; that.number[l] == 0; l--);

    int ds = l + 1; div.number.resize(ds);

    for (int i = 0; i < ds; i++)

    {

        div.number[i] = that.number[i];

    }

    for (l = number.size() - 1; number[l] == 0; l--);

    int newdiff = diff - point + that.point;

    short x = 0; short d = div.number.back(); current.number += '\0';

    for (; l > -1 - newdiff; l--)

    {

        current.number += '\0';

        for (int i = current.number.size() - 1; i > 0; i--)

        {

            current.number[i] = current.number[i - 1];

        }

        if (l < 0) { current.number[0] = '\0'; }

        else { current.number[0] = number[l]; }

        if (current.number.back() == 0) { current.number.pop_back(); }

        if (div <= current)

        {

            if (current.number.size() == ds) { x = current.number.back() / d; }

            else { x = (10 * current.number.back() + current.number[current.number.size() - 2]) / d; }

            real tmp; tmp.number += x;

            tmp = tmp * div;

            current = current - tmp;

            while (current.sign == -1) { current = current + div; x--; }// 223/23!=11,10

            result.number += x;

        }

        else { result.number += '\0'; }

    }

    l = result.number.size();

    for (int i = 0; i < l / 2; i++)

    {

        char c = result.number[l - i - 1];

        result.number[l - 1 - i] = result.number[i];

        result.number[i] = c;

    }

    while (result.number.empty() == false && result.number.back() == 0) { result.number.pop_back(); }//清空首0

    for (l = result.number.size() - 1; l < diff - 1; l++) { result.number += '\0'; }

    if (that <= *this == false) { result.number += '\0'; }

    if (diff < 0) {

        if (result.zero() == false) {

            ds = result.number.size();

            for (l = diff; l < 0; l++) { result.number += result.number[ds + l]; }

            for (l = ds + diff; l > -1; l--) { result.number[l - diff] = result.number[l]; }

            for (l = 0; l < -diff; l++) { result.number[l] = '\0'; }

        }

        result.point = 0;

    }

    else { result.point = diff; }

    result.sign = sign * that.sign;

    return result;

}

void real::to2(string& str)

{

    do

    {

        if (this->intdivide2(0) == 0)

        {

            *this = *this - real("1");

            this->intdivide2(0);

            str += (char)(1);

        }

        else {

            str += char(0);

        }

    } while (this->number.size() > 1 || this->number[0] != 0);

}

const real real::operator ^(const real& that)const

{

    if (that.zero()) { return real("1"); }

    if (that == real("1")) { return (*this); }

    if (that.point == 0)

    {

        if (that.sign == -1) { real a = that; a.sign = 1; return real("1") / (*this ^ a); }

        real tmp = that;

        string str;

        tmp.to2(str);

        tmp = (*this);

        real result;

        if (str[0] == 1) { result = tmp; }

        else { result = real("1"); }

        for (short i = 1; i < str.size(); i++)

        {

            tmp = tmp * tmp;

            if (tmp.number.size() > 120000) { cout << "^ too big!"; exit(0); }

            if (str[i] == 1) { result = result * tmp; }

        }

        return result;

    }

    cout << "use pow"; exit(0);

}

const real real::pow(const real& that)const

{

    if (this->zero()) { if (that.sign == 1) { return real("0"); }cout << "pow wrong!"; exit(0); }

    if (that.sign == -1) {

        real a = that; a.sign = 1; short record = diff;

        if (this->number.back() != '\0') {

            a = this->pow(a);

            if (a.point == 0) { diff = 0; }

            else {

                diff = 2 * a.number.size() - a.point - 3;//控制得到更高精度

                if (a.point == 0) { for (int j = 0; a.number[j] == 0; j++, diff--); }

            }

            a = real("1") / a;

        }

        else {

            diff = 180;

            a = (real("1") / (*this)).pow(a);

        }

        diff = record;

        return a;

    }

    else {

        real a;

        if (sign == -1) {

            int sig = -1;

            if (that.point) {

                a.number = that.number;

                short count = a.intdivide2();

                if (count < that.point) { cout << "pow wrong!"; exit(0); }

                if (count > that.point) { sig = 1; }

            }

            else if (that.number[that.point] % 2 == 0) { sig = 1; }

            a = *this; a.sign = 1;

            a = (that * (a.log())).exp();

            a.sign = sig;

        }

        else { a = (that * (this->log())).exp(); }

        a.clear(140 - that.number.size() + that.point);//e^170远超范围,140=142-2,logmax为10^2级别

        return a;

    }

}

bool real::operator <=(const real& that)const

{

    int i = (number.size() - point) - (that.number.size() - that.point);

    if (i < 0) { return true; }

    if (i > 0) { return false; }

    i = number.size() - 1;

    for (int j = that.number.size() - 1; i > -1 && j > -1; i--, j--)

    {

        short k = (number[i] - that.number[j]);

        if (k < 0) { return true; }

        if (k > 0) { return false; }

    }

    for (; i > -1 && number[i] == 0; i--);

    if (i > -1) { return false; }

    return true;

}

bool real::operator ==(const real& that)const

{

    int l1 = number.size(), l2 = that.number.size();

    if (sign != that.sign || l1 - point != l2 - that.point) { return false; }

    int start1 = 0, start2 = 0;

    for (; start1 < point && number[start1] == 0; start1++);

    for (; start2 < that.point && that.number[start2] == 0; start2++);

    if (point - start1 != that.point - start2) { return false; }

    int i = 0;

    for (; i < l1 - point; i++)

    {

        if (number[i + start1] != that.number[i + start2]) { return false; }

    }

    return true;

}

bool real::zero()const

{

    for (char c : number)

    {

        if (c != 0) { return false; }

    }

    return true;

}

bool real::positive()const

{

    if (sign == 1) { return true; }

    return false;

}

const real real::radian()const

{

    short record = diff;

    diff = 0;

    real count = (*this) / real("360");

    real result = (*this) - (count * real("360"));

    diff = 200;

    if (result.sign == -1) { result = result + real("360"); }

    result = (result * pi_2) / real("90");

    diff = record;

    return result;

}

const real real::cos()const

{

    if (*this <= real("100000000"))

    {

        real b = *this;

        short record = diff; diff = 500;

        b = (b * b) / c_2_512;

        for (int i = 0; i < 256; i++)

        {

            b = b * (real("4") - b);

            b.clean(-500);

        }

        b = b / real("2");

        b = real("1") - b;

        diff = record;

        if (*this <= real("10")) { b.clean(-148); }

        else if (*this <= real("100000")) { b.clean(-138); }

        else { b.clean(-127); }

        return b;

    }

    cout << "cos too big!"; exit(0);

}

const real real::sin()const

{

    return (pi_2 - *this).cos();

}

const real real::tan()const

{

    short record = diff;

    diff = 500;

    real b = *this * real("2");

    b = (b.sin()) / (b.cos() + real("1"));

    diff = record;

    b.clean(-123);

    return b;

}

void real::sqrt(int level)

{

    real result;

    if (*this <= real("1")) { result = real("1"); }

    else {

        int l = (number.size() - point) / 2;

        result = real(l);

    }

    short record = diff; diff = -level + 9;

    real t = real("0.5") * (result - ((*this) / result));

    const real flag(level - 1);

    while (flag <= t)

    {

        result = result - t;

        t = real("0.5") * (result - ((*this) / result));

    }

    diff = record;

    *this = result;

}

const real real::root(const real& that)const

{

    if (that.point || that.sign == -1 || (that.number.back() % 2 == 0 && sign == -1)) { cout << "root wrong!"; exit(0); }

    if (that.zero() || *this == real("1")) { return real("1"); }

    if (this->zero()) { return real("0"); }

    if (that == real("1")) { return *this; }

    short record = diff;

    diff = 150;

    real a = *this;

    a.sign = 1;

    a = ((a.log()) / that).exp();

    a.sign = sign;

    a.clear(137);

    diff = record;

    return a;

}

const real real::newtonroot(const real& that, int level)const

{

    cout << "newtonroot...\n";

    short record = diff;

    const real that_ = that - real("1");

    real base = *this; int l = 0;

    while (base <= real("1"))

    {

        base = base * (real("10") ^ that);

        l--;

        level++;

    }

    real result(base), adjust(l);

    diff = -level + 1;

    if (result <= real("10") == false)

    {

        l = (base.number.size() - base.point) / that.toint();

        result = real(l + 1);

        result.sign = sign;

    }

    real tmp = ((result ^ that) - base) / (that * (result ^ that_));

    const real flag(level);

    while (flag <= tmp)

    {

        result = result - tmp;

        result.clean(level);

        tmp = ((result ^ that) - base) / (that * (result ^ that_));

    }

    diff = record;

    result = result * adjust;

    return result;

}

const real real::cosh()const

{

    if (*this <= real("100000")) {

        real b = *this;

        short record = diff; diff = 500;

        b = (b * b) / c_2_512;

        for (int i = 0; i < 256; i++)

        {

            b = b * (real("4") + b);

            b.clean(-500);

        }

        b = b / real("2");

        b = real("1") + b;

        diff = record;

        int l = b.number.size() - b.point;

        if (number.back() == 0) { b.clear(154); }

        else if (l == 1) { b.clear(151); }

        else if (*this <= real("170")) { b.clear(147); }

        else if (l < 4) { b.clear(145); }

        else { b.clear(139); }

        return b;

    }

    else { cout << "cosh too big!"; exit(0); }

}

const real real::sinh()const

{

    if (*this <= real("1"))

    {

        real a = real("1"), b(a), c(*this), sum("0");

        const real t(c * c);

        short record = diff; diff = 500;

        for (int i = 0; i < 100; i++)

        {

            sum = sum + (c / a);

            b.tailadd(1);

            a = a * b;

            b.tailadd(1);

            a = a * b;

            c = c * t;

        }

        sum.clean(-150);

        diff = record;

        return sum;

    }

    if (real("175") <= *this) { return this->cosh(); }

    real tmp = this->cosh();

    int l = tmp.point;

    tmp = (tmp * tmp) - real("1");

    tmp.sqrt(-l);

    tmp.sign = sign;

    return tmp;

}

const real real::tanh()const

{

    real a = *this * real("2");

    short record = diff; diff = 130;

    a = a.exp();

    a = (a - real("1")) / (a + real("1"));

    diff = record;

    a.clear(130);

    return a;

}

const real real::exp()const

{

    if (sign == -1) {

        real a = *this; a.sign = 1; a = a.exp();

        short record = diff; diff = (a.number.size() - a.point - 2) + 130;

        a = real("1") / a; diff = record; return a;

    }

    if (*this <= real("1"))

    {

        real a = real("1"), b(a), c(*this), sum("1");

        short record = diff; diff = 500;

        for (int i = 0; i < 200; i++)

        {

            sum = sum + (c / a);

            b.tailadd(1);

            a = a * b;

            c = c * (*this);

        }

        sum.clean(-150);

        diff = record;

        return sum;

    }

    if (*this <= real("100000")) {

        real b = this->cosh(); int l = b.point;

        if (real("170") <= *this) { b = b * real("2"); b.clear(138); }

        else {

            real tmp = b;

            tmp = (tmp * tmp) - real("1");

            tmp.sqrt(-l);

            b = b + tmp;

            b.clear(146);

        }

        return b;

    }

    else { cout << "exp too big!"; exit(0); }

}

const real real::arccosh()const

{

    if (number.back() == 0 || sign == -1) { cout << "arccosh wrong!"; exit(0); }

    real a = ((*this) * (*this)) - real("1");

    a.sqrt(-200);

    return (*this + a).log();

}

const real real::arcsinh()const

{

    real a = real("1") + ((*this) * (*this));

    a.sqrt(-200);

    a = (*this + a).log();

    a.sign = sign;

    return a;

}

const real real::arctanh()const

{

    if (real("1") <= *this) { cout << "arctanh wrong!"; exit(0); }

    real a(*this); short record = diff;

    if (*this <= real("0.4"))

    {

        real b("1"), sum("0");

        const real t = a * a;

        diff = 1000;

        for (int i = 0; i < 200; i++)

        {

            sum = sum + (a / b);

            a = a * t;

            b.tailadd(2);

        }

        diff = record;

        sum.clear(150);

        return sum;

    }

    else

    {

        diff = 400;

        a = ((a + real("1")) / (real("1") - a)).log() * real("0.5");

        a.clean(-138);

        return a;

    }

}

const real real::log()const

{

    if (sign == -1 || this->zero()) { cout << "log wrong!"; exit(0); }

    if (*this == real("1")) { return real("0"); }

    short record = diff;

    if ((*this) <= real("1")) { diff = 150; real a = (real("1") / (*this)).log(); diff = record; a.sign = -1; return a; }

    if (number.size() - point > 100) { cout << "log too big!"; exit(0); }

    real b("0"), a = *this;

    real c("1.5"), p("2");

    while (c <= a)

    {

        a.sqrt(-8);

        b.tailadd(1);

    }

    b = p ^ b;

    p.number[0] = 1;

    a = a - p;

    real sum("0"), t(p);

    c = a; c.sign = -1;

    diff = 20;

    for (int i = 0; i < 20; i++)

    {

        sum = sum + a / t;

        a = a * c;

        t.tailadd(1);

    }

    b = sum * b;

    b.clean(-6);

    diff = 150;

    a = (*this / (b.exp())) - p;

    sum = real("0"); t = p;

    c = a; c.sign = -1;

    for (int i = 0; i < 30; i++)

    {

        sum = sum + a / t;

        a = a * c;

        t.tailadd(1);

    }

    diff = record;

    b = b + sum;

    if (real("170") <= b) { b.clear(140); }

    else { b.clear(142); }

    return b;

}

const real real::arccos()const

{

    if (*this == real("1")) { return real("0"); }

    if (*this <= real("1"))

    {

        real t(*this);

        if (this->sign == -1) { t.sign = 1; real c = pi_2 * real("2") - t.arccos(); c.clear(170); return c; }

        real m("1"), p("1"), q("2");

        short record = diff; diff = 1000;

        if (*this <= real("0.43")) {

            real sum("0");

            const real a = t * t;

            for (int i = 0; i < 200; i++)

            {

                sum = sum + (t / p);

                t = (a * t * p) / q;

                p.tailadd(2); q.tailadd(2);

            }

            diff = record;

            sum = pi_2 - sum;

            sum.clear(172); return sum;

        }

        while (t <= real("0.9029"))

        {

            t = (t + p) / q;

            t.sqrt(-200);

            m = m * q;

        }

        t = real("1") - (t * t);

        t.sqrt(-200);

        m = m * (pi_2 - (t.arccos()));

        diff = record;

        m.clear(170); return m;

    }

    cout << "arccos wrong!"; exit(0);

}

const real real::arcsin()const

{

    real t = real("1") - ((*this) * (*this));

    if (t.sign == -1) { cout << "arcsin wrong!"; exit(0); }

    t.sqrt(-300);

    t = t.arccos();

    t.sign = sign;

    t.clear(168);

    return t;

}

const real real::arctan()const

{

    short record = diff;

    diff = 500;

    real a = real("1") / (real("1") + ((*this) * (*this)));

    a.sqrt(-300);

    a = a.arccos();

    a.sign = sign;

    diff = record;

    return a;

}

class complex

{

private:

    real a, b;

public:

    complex() {}

    complex(const string& x) :a(real(x)) {}

    complex(const real& x) :a(x) {}

    complex(const string& x, const string& y) :a(real(x)), b(real(y)) {}

    complex(const real& x, const  real& y) :a(x), b(y) {}

    void get() { a.get(); b.get(); }

    void display(bool all = true)const;

    const real realpart()const { return a; }

    const real imaginarypart()const { return b; }

    const real mod()const;

    const real arg()const;

    const complex operator-()const;

    const complex operator +(const complex& that)const;

    const complex operator -(const complex& that)const;

    const complex operator *(const complex& that)const;

    const complex operator /(const complex& that)const;

    const complex operator ^(const real& that)const;

    const complex exp()const;

    const complex sin()const;

    const complex cos()const;

    const complex log()const;

    friend class method;

};

const complex real::operator +(const complex& that)const

{

    return that + *this;

}

const complex real::operator -(const complex& that)const

{

    return -that + *this;

}

const complex real::operator *(const complex& that)const

{

    return that * (*this);

}

const complex real::operator /(const complex& that)const

{

    return complex(*this) / that;

}

void complex::display(bool all)const

{

    cout << "realpart\n";

    this->a.display(all);

    cout << "imaginarypart\n";

    this->b.display(all);

}

const real complex::mod()const

{

    real c = (a * a) + (b * b);

    c.sqrt(-200);

    c.clean(-180);

    return c;

}

const real complex::arg()const

{

    short record = real::diff;

    real::diff = 200;

    real c = (b / a).arctan();

    real::diff = record;

    return c;

}

const complex complex::operator-()const

{

    complex t; t.a = -a; t.b = -b; return t;

}

const complex complex::operator +(const complex& that)const

{

    return complex(a + that.a, b + that.b);

}

const complex complex::operator -(const complex& that)const

{

    return complex(a - that.a, b - that.b);

}

const complex complex::operator *(const complex& that)const

{

    return complex((a * that.a) - (b * that.b), (a * that.b) + (b * that.a));

}

const complex complex::operator /(const complex& that)const

{

    real c = (that.a * that.a) + (that.b * that.b);

    return complex(((a * that.a) + (b * that.b)) / c, ((b * that.a) - (a * that.b)) / c);

}

const complex complex::operator ^(const real& that)const

{

    if (that.zero()) { return complex("1", "0"); }

    if (that == real("1")) { return (*this); }

    if (that.point == 0)

    {

        if (that.sign == -1) { real a = that; a.sign = 1; return complex("1", "0") / (*this ^ a); }

        real tmp = that; string str; tmp.to2(str);

        complex t = (*this);

        complex result;

        if (str[0] == 1) { result = t; }

        else { result = complex("1", "0"); }

        for (short i = 1; i < str.size(); i++)

        {

            t = t * t;

            if (str[i] == 1) { result = result * t; }

        }

        return result;

    }

    cout << "^ wrong"; exit(0);

}

const complex complex::exp()const

{

    real c = a.exp();

    int l = c.number.size(), j;

    if (c.point) { j = -c.point; }//also make full use of e^(-x)

    else { j = l - 138; }

    l -= c.point;

    real x = b.cos(), y = b.sin();

    int l1;

    if (x.point) {

        l1 = l - x.point;

        if (l1 < j) { l1 = j; }

        x = x * c; x.clean(l1 + 2);

    }

    else { x = x * c; }

    if (y.point) {

        l1 = l - y.point;

        if (l1 < j) { l1 = j; }

        y = y * c; y.clean(l1 + 2);

    }

    else { y = y * c; }

    return complex(x, y);

}

const complex complex::sin()const

{

    complex c;

    c.a = b; c.a.sign = -b.sign;

    c.b = a;

    c = c.exp();

    int l1 = c.a.point, l2 = c.b.point;

    complex d;

    d.a = b;

    d.b = a; d.b.sign = -a.sign;

    d = d.exp();

    if (d.a.point < l1) { l1 = d.a.point; }

    if (d.b.point < l2) { l2 = d.b.point; }

    short record = real::diff;

    c = c - d;

    if (l1) { real::diff = l1 - 1; c.a = c.a / real("2"); }

    else { c.a.clean(0); c.a.intdivide2(0); c.a.clear(135); }

    if (l2) { real::diff = l2 - 1; c.b = c.b / real("2"); }

    else { c.b.clean(0); c.b.intdivide2(0); c.b.clear(135); }

    real::diff = record;

    d.a = c.b;

    d.b = c.a; d.b.sign = -c.a.sign;

    return d;

}

const complex complex::cos()const

{

    complex c;

    c.a = b; c.a.sign = -b.sign;

    c.b = a;

    c = c.exp();

    int l1 = c.a.point, l2 = c.b.point;

    complex d;

    d.a = b;

    d.b = a; d.b.sign = -a.sign;

    d = d.exp();

    if (d.a.point < l1) { l1 = d.a.point; }

    if (d.b.point < l2) { l2 = d.b.point; }

    short record = real::diff;

    c = c + d;

    if (l1) { real::diff = l1 - 1; c.a = c.a / real("2"); }

    else { c.a.clean(0); c.a.intdivide2(0); c.a.clear(135); }

    if (l2) { real::diff = l2 - 1; c.b = c.b / real("2"); }

    else { c.b.clean(0); c.b.intdivide2(0); c.b.clear(135); }

    real::diff = record;

    return c;

}

const complex complex::log()const

{

    return complex(this->mod().log(), this->arg());

}

class method

{

public:

    static void test();

    static const real twochordmethod(real& a, real& b, real(*f)(real& c), int level);//set proper diff

    static const real bisectionmethod(real& a, real& b, real(*f)(real& c), int level);

    static const real newtonmethod(real& a, real(*f)(real& c), real(*df)(real& c), int level);

    static const complex newtonmethod(complex& a, complex(*f)(complex& c), complex(*df)(complex& c), int level);

    static const real euclidmethod(const real& a, const real& b, real& x, real& y);

    static void euclidmethod(const real& a, const real& b, const real& c);

    static void drandkernermethod(complex(*f)(complex& c), size_t n,int level,const complex& first=real("1"),const real& init=real("1.1"));//div0wrong改变init

};

void method::drandkernermethod(complex(*f)(complex& c), size_t n,int level,const complex& first,const real& init)

{

    cout << "\ndrandkernermethod...\n";

    if(n==0){cout<<"none or all\n";return;}

    complex* a = new complex[n];

    a[0] = complex(real("0"),init);

    for (int i = 1; i < n; i++)

    {

        a[i-1].a.tailadd(1);

        a[i] = complex(a[i-1].a, real("1"));

    }

    a[n - 1] = complex("-1", "-1");

    real flag(2*level);

    short record = real::diff;

    real::diff = -level + 1;

    bool mark;

    do

    {

        mark = false;

        for (int i = 0; i < n; i++)

        {

            complex tmp = first;

            for (int j = 0; j < n; j++)

            {

                if (i != j) { tmp = tmp * (a[i] - a[j]); }

            }

            tmp = f(a[i]) / (tmp);

            if (!mark&&flag <= (tmp.a * tmp.a)&&flag<=(tmp.b * tmp.b)) { mark = true; }

            a[i]=a[i]-tmp;

        }

    }while (mark);

    real::diff = record;

    real* m=new real[n];

    bool* cc=new bool[n];

    for (int i = 0; i < n; i++)

    {

        a[i].a.clean(level);a[i].b.clean(level);

        m[i]=(a[i].a*a[i].a)+(a[i].b*a[i].b);

        cc[i]=true;

    }

    int count=0;

    for(int i=0;i<n;)

    {

        int k=i;

        if(cc[i]){

            for(int j=i+1;j<n;j++){

                    if(cc[j]&&m[k]<=m[j]){k=j;}

                }

            cout<<"\nroot"<<++count<<endl;

            a[k].display();

            cc[k]=false;

        }

        if(k==i){i++;}

    }

    delete[]a;

    delete[]m;

    delete[]cc;

}

void method::euclidmethod(const real& a, const real& b, const real& c)

{

    cout << "\neuclidmethod...\n";

    int i = a.point > b.point ? a.point : b.point;

    if (c.point > i) { i = c.point; }

    real t(i), a1 = a * t, b1 = b * t, c1 = c * t;

    real x1, y1;

    t = euclidmethod(a1, b1, x1, y1);

    cout << "ax+by=c\na\n";

    a1.display(); cout << "b\n";

    b1.display(); cout << "c\n";

    c1.display(); cout << "gcd(a,b)\n";

    a1 = c1.intdiv(t, b1);

    t.sign = 1;

    t.display();

    if (b1.zero())

    {

        x1 = x1 * a1; y1 = y1 * a1;

        cout << "x\n";

        x1.display();

        cout << "y\n";

        y1.display();

    }

    else { cout << "none\n"; }

}

const real method::euclidmethod(const real& a, const real& b, real& x, real& y)

{

    if (a.zero()) { y = real("1"); x = real("0"); return b; }

    else {

        real m, n = b.intdiv(a, m);

        real g = euclidmethod(m, a, x, y);

        m = x;

        x = y - (n * x);

        y = m;

        return g;

    }

}

const complex method::newtonmethod(complex& a, complex(*f)(complex& c), complex(*df)(complex& c), int level)

{

    cout << "\nnewtonmethod...\n";

    short record = real::diff; real::diff = -level + 1;

    const real flag(level); complex tmp;

    do

    {

        tmp = f(a) / df(a);

        a = a - tmp;

        a.a.clean(level);

        a.b.clean(level);

    } while (flag <= tmp.a && flag <= tmp.b);

    real::diff = record;

    return a;

}

const real method::newtonmethod(real& a, real(*f)(real& c), real(*df)(real& c), int level)

{

    cout << "\nnewtonmethod...\n";

    short record = real::diff; real::diff = -level + 1;

    const real flag(level); real tmp;

    do

    {

        tmp = f(a) / df(a);

        a = a - tmp;

        a.clean(level);

    } while (flag <= tmp);

    real::diff = record;

    return a;

}

const real method::bisectionmethod(real& a, real& b, real(*f)(real& c), int level)

{

    cout << "\nbisectionmethod...\n";

    real* m = &b, * n = &a;

    if (f(b).sign == -1) { real* tmp = m; m = n; n = tmp; }

    const real flag(level), two("2");

    real x;

    short record = real::diff; real::diff = -level + 1;

    while (flag <= *m - *n)

    {

        x = (*m + *n) / two;

        if (f(x).sign == 1) { *m = x; }

        else { *n = x; }

    }

    real::diff = record;

    m->clean(level);

    return *m;

}

const real method::twochordmethod(real& a, real& b, real(*f)(real& c), int level)

{

    cout << "\ntwochordmethod...\n";

    real y1, y2;

    real* first = &a, * second = &b;

    const real flag(level);

    while (1)

    {

        y1 = f(*first);

        y2 = f(*second);

        if (y1.sign * y2.sign == -1 && (*first - *second) <= flag) { break; }

        *first = (((*first) * y2) - ((*second) * y1)) / (y2 - y1);

        real* tmp = second;

        second = first;

        first = tmp;

    }

    first->clean(level);

    return *first;

}

void method::test()

{

    real::diff = 10;

    while (1)

    {

        cout << "加减乘除:\n";

        cout << "+.....-.....*...../.....=\n";

        cout << "阶乘组合:\n";

        cout << "! a.....!! b.....A c.....C d\n";

        cout << "次方估计:\n";

        cout << "^ e.....root f.....pow g\n";

        cout << "弧度三角:\n";

        cout << "sin h.....cos i..... tan j\n";

        cout << "角度三角:\n";

        cout << "sin k.....cos l..... tan m\n";

        cout << "反三角:\n";

        cout << "arcsin n.....arccos o.....arctan p\n";

        cout << "e相关:\n";

        cout << "exp q.....log r\n";

        cout << "双曲函数:\n";

        cout << "sinh s.....cosh t..... tanh u\narcsinh v.....arccosh w.....arctanh x\n";

        cout << "=>diff:" << real::diff << ".....y\n";

        cout << "=>continue.....z\n\n";

        string t;

        cin >> t;

        char c = t[0];

        cout << "mode " << c << endl;

        real a, b;

        short l = real::diff;

        a.get();

        switch (c)

        {

        case '+':

            b.get();

            (a + b).display();

            break;

        case '-':

            b.get();

            (a - b).display();

            break;

        case '*':

            b.get();

            (a * b).display();

            break;

        case '/':

            b.get();

            (a / b).display();

            break;

        case '=':

            a.halfadjust();

            a.display(); break;

        case 'a':

            a.factorial().display();

            break;

        case 'b':

            a.factorial(0).display();

            break;

        case 'c':

            b.get();

            a.chooseandrank(b).display();

            break;

        case 'd':

            b.get();

            a.choose(b).display();

            break;

        case 'e':

            b.get();

            (a ^ b).display();

            break;

        case 'f':

            b.get();

            a.root(b).display();

            break;

        case 'g':

            b.get();

            a.pow(b).display();

            break;

        case 'h':

            a.sin().display();

            break;

        case 'i':

            a.cos().display();

            break;

        case 'j':

            a.tan().display();

            break;

        case 'k':

            a.radian().sin().display();

            break;

        case 'l':

            a.radian().cos().display();

            break;

        case 'm':

            a.radian().tan().display();

            break;

        case 'n':

            a = a.arcsin();

            a.display();

            real::diff = 150;

            a = a * real("90") / real::pi_2;

            a.display();

            break;

        case 'o':

            a = a.arccos();

            a.display();

            real::diff = 150;

            a = a * real("90") / real::pi_2;

            a.display();

            break;

        case 'p':

            a = a.arctan();

            a.display();

            real::diff = 150;

            a = a * real("90") / real::pi_2;

            a.display();

            break;

        case 'q':

            a.exp().display();

            break;

        case 'r':

            a.log().display();

            break;

        case 's':

            a.sinh().display();

            break;

        case 't':

            a.cosh().display();

            break;

        case 'u':

            a.tanh().display();

            break;

        case 'v':

            a.arcsinh().display();

            break;

        case 'w':

            a.arccosh().display();

            break;

        case 'x':

            a.arctanh().display();

            break;

        case 'y':

            l = a.toint(); if (l > -1) { real::diff = l; }

        default:

            system("CLS");

            continue;

        }

        real::diff = l;

        while (c != 'z') {

            cin >> c;

        }

        system("CLS");

    }

}

class poly

{

private:

    int number;

    real* a;

    real* b;

    struct node {

        poly* h;

        node* next = nullptr;

    }*first = nullptr, * last = nullptr;

    void transform();

    void sturm();

    void generate(real*& s, real*& t, int& l1, int& l2, real* mark);

    void div(real* x, real* y, int l1, int l2, real* mark);

    int snumber(const real& x);

    int get(int& c1, int& c2);

    poly() {};

    static bool check(const string& str);

    poly(const string& expr, bool& mark);//降幂排列,可以解析即判true,expr不一定正确

    void operator=(const poly& that);

public:

    static poly* get();

    static poly* create(const string& expr);

    void print()const;

    const complex f(const complex& n)const;

    const real f(const real& n)const;

    poly* df(size_t n = 1)const;

    void analyse(int level = -10);

    ~poly();

};

poly* poly::get()

{

    bool m; string str;

    cin >> str;

    poly* tmp = new poly(str, m);

    while (m == false) { delete tmp; cout << "wrong input\n"; cin >> str; tmp = new poly(str, m); }

    return tmp;

}

poly* poly::create(const string& expr)

{

    bool m; poly* tmp = new poly(expr, m);

    if (m) { return tmp; }

    cout << "poly wrong"; exit(0);

}

int poly::snumber(const real& x)

{

    int mark = 0, count = 0;

    node* p;

    for (p = first; p; p = p->next) {

        real tmp(p->h->f(x));

        if (tmp.zero()) { continue; }

        int k = tmp.sign;

        if (k * mark == -1) { count++; }

        mark = k;

    }

    return count;

}

void poly::analyse(int level)

{

    cout << endl;

    if (number == 1 && a[0].zero() && b[0].zero()) { cout << "all\n"; return; }

    poly* tmp = new poly;

    *tmp = *this;

    tmp->transform();

    int c1, c2, n = tmp->get(c1, c2);

    if (n == 0) { cout << "none\n"; delete tmp; return; }

    real p, q; int p1 = 0, q1 = 0;

    do {

        p = real(++p1);

        p.sign = -1;

    } while (tmp->snumber(p) != c2);

    do {

        q = real(++q1);

    } while (tmp->snumber(q) != c1);

    int l = p1 > q1 ? p1 : q1;

    real* a = new real[n]; real* b = new real[n];

    for (int i = 0; i < n; i++) { a[i] = p; b[i] = q; }

    const real c("2");

    short record = real::diff;

    while (l > level) {

        l--;

        p = real(l);

        real::diff = -l + 1;

        for (int i = 0; i < n; i++)

        {

            while (p <= (b[i] - a[i]))

            {

                q = (a[i] + b[i]) / c;

                if (tmp->snumber(q) >= c2 - i) { a[i] = q; }

                else { b[i] = q; }

            }

        }

    }

    if (l > -1) { l = 0; }

    else { l = -l + 1; }

    real::diff = record;

    for (int i = 0; i < n; i++)

    {

        cout << "root " << i + 1 << endl;

        if (tmp->f(a[i]).zero()) { a[i].zerooff(); a[i].show(); }

        else if (tmp->f(b[i]).zero()) { b[i].zerooff(); b[i].show(); }

        else {

            a[i].addzero(l); b[i].addzero(l);

            p = a[i]; p.halfadjust();

            q = b[i]; q.halfadjust();

            if (tmp->f(p).zero()) { p.zerooff(); p.show(); }

            else if (tmp->f(q).zero()) { q.zerooff(); q.show(); }

            else { a[i].show(); cout << endl; b[i].show(); }

        }

        cout << endl;

    }

    delete tmp;

}

void poly::transform()

{

    sturm();

    if (last->h->b[last->h->number - 1].zero() == false) {

        node* record = last->next; last->next = nullptr;

        this->~poly(); *this = *(record->h);

        sturm();

    }

    for (node* p = first; p != last; p = p->next)

    {

        real* tmp = p->h->a;

        int n = p->h->number;

        real g = tmp[n - 1]; g.sign = 1;

        for (int i = n - 2; i > 0; i--)

        {

            g = g.gcd(tmp[i]);

        }

        if (tmp[0].zero() == false) { g = g.gcd(tmp[0]); }

        for (int i = n - 1; i > -1; i--)

        {

            real cc;

            tmp[i] = tmp[i].intdiv(g, cc);

            tmp[i].zerooff();

        }

    }

    if (last->h->a[0].sign == 1) { last->h->a[0] = real("1"); }

    else { last->h->a[0] = real("-1"); }

   

    first->h->print();

}

int poly::get(int& c1, int& c2)

{

    c1 = 0, c2 = 0; int mark1 = 0, mark2 = 0;

    node* p;

    for (p = first; p != last; p = p->next) {

        if (p->h->a[p->h->number - 1].zero() == false)

        {

            int k = -1;

            if (p->h->b[p->h->number - 1].number[0] % 2 == 0) { k = 1; }

            if (p->h->a[p->h->number - 1].sign == 1) {

                if (mark1 == -1) { c1++; }mark1 = 1;

                if (mark2 == -k) { c2++; }mark2 = k;

            }

            else {

                if (mark1 == 1) { c1++; }mark1 = -1;

                if (mark2 == k) { c2++; }mark2 = -k;

            }

        }

    }

    int k = last->h->a[last->h->number - 1].sign;

    if (mark1 * k == -1) { c1++; }

    if (mark2 * k == -1) { c2++; }

    return c2 - c1;

}

void poly::sturm()

{

    if (!first) {

        int max = 0;

        for (int i = 0; i < number; i++) { if (this->a[i].point > max) { max = a[i].point; } }

        first = new node; first->h = new poly;

        for (int i = 0; i < number; i++) { a[i] = a[i] * real(max); }

        *(first->h) = *(this);

    }

    if (this->b[number - 1].zero()) { last = first; return; }

    last = new node; last->h = this->df(1);

    first->next = last;

    if (this->b[number - 1] <= real("1")) { return; }

    int l1 = b[number - 1].toint(), ddd = l1;

    real* mark = new real[l1 + 1]; mark[0].number += '\0';

    for (int i = 0; i < l1; i++) { mark[i + 1] = mark[i]; mark[i + 1].tailadd(1); }

    real* s = new real[l1 + 1], * t = new real[l1], * s_ = new real[l1 + 1];

    for (int i = l1, c = number - 1; i > 0; i--) {

        if (mark[i] == b[c]) { s[i] = s_[i] = a[c]; t[i - 1] = a[c] * mark[i]; c--; }

    }

    int j = b[0].toint(); s[j] = s_[j] = a[0];

    if (j) { t[j - 1] = a[0] * mark[j]; }

    j = l1 - 1;

    while (l1 > 0) { generate(s, t, l1, j, mark); }

    if (j) {div(s_, t, ddd, j, mark);}

    delete[]mark;

    delete[]s_;

    delete[]s;

    delete[]t;

}

void poly::div(real* x, real* y, int l1, int l2, real* mark)

{

    const int ff = y[l2].number.size() - y[l2].point;

    int gap = l1 - l2;

    real* result = new real[gap + 1]; int pos = gap;

    for (int b = l1; b > -1;) {

        real g = y[l2].gcd(x[b]);

        real cc;

        g = y[l2].intdiv(g, cc);

        for (int i = b; i > -1; i--) { x[i] = x[i] * g; }

        for (int i = gap; i > pos; i--) { result[i] = result[i] * g; }

        result[pos] = x[b].intdiv(y[l2], cc);

        for (int i = l2 - 1, j = 1; i > -1; i--, j++) { x[b - j] = x[b - j] - (result[pos] * y[i]); }

        b--; pos--;//少算一个

        while (b > -1 && x[b].zero()) { b--; pos--; }

    }

    last->next = new node; node*tmp = last->next; tmp->h = new poly;

    int count = 0, j = 0;

    for (int i = 0; i < gap + 1; i++) { if (result[i].zero() == false) { count++; } }

    if (result[0].zero()) { count++; j = 1; }//为了求导补0

    tmp->h->a = new real[count]; tmp->h->b = new real[count]; tmp->h->number = count;

    count = j;

    for (int i = 0; i < gap + 1; i++) {

        if (result[i].zero() == false) { tmp->h->a[count] = result[i]; tmp->h->b[count] = mark[i]; count++; }

    }

}

void poly::generate(real*& s, real*& t, int& l1, int& l2, real* mark)

{

    int gap = l1 - l2;//1

    while (gap > -1) {

        real g = s[l1].gcd(t[l2]);

        real cc;

        real s1 = t[l2].intdiv(g, cc), t1 = s[l1].intdiv(g, cc);

        t1.sign = s1.sign * t1.sign;

        s1.sign = 1;

        for (int i = l1; i > -1; i--) { s[i] = s[i] * s1; }

        for (int i = --l1; i > gap - 1; i--) { s[i] = s[i] - (t[i - gap] * t1); }//少算一个

        while (l1 > -1 && s[l1].zero()) { l1--; }

        gap = l1 - l2;

    }

    if (l1 > -1) {

        real* p = new real[l1 + 1];

        for (int i = 0; i < l1 + 1; i++) { p[i] = s[i]; }

        delete[]s;

        int count = 0;

        for (int i = 0; i < l1 + 1; i++) {

            if (p[i].zero() == false) { count++; p[i].sign = -p[i].sign; }

        }

        last->next = new node; last = last->next; last->h = new poly;

        last->h->a = new real[count]; last->h->b = new real[count];

        last->h->number = count;

        count = 0;

        for (int i = 0; i < l1 + 1; i++) {

            if (p[i].zero() == false) {

                last->h->a[count] = p[i]; last->h->b[count] = mark[i];

                count++;

            }

        }

        s = t; t = p;

        int l = l2; l2 = l1; l1 = l;

    }

}

poly::poly(const string& expr, bool& mark)

{

    number = 1;

    for (char c : expr) {

        if (c == 'x') { number++; }

    }

    a = new real[number]; b = new real[number];

    int i = 0, l = expr.size();

    for (int count = number - 1; i < l && count>-1; count--) {

        if (expr[i] != 'x') {

            int sign = 1;

            if (expr[i] == '+') { i++; }

            else if (expr[i] == '-') { i++; sign = -1; }

            string tmp;

            for (; i < l && ((expr[i] < '9' + 1 && expr[i]>'0' - 1) || expr[i] == '.'); i++) { tmp += expr[i]; }

            if (tmp.empty()) { a[count] = real("1"); }

            else { if (real::check(tmp) == false) { break; }a[count] = real(tmp); }

            a[count].sign = sign;

        }

        else { a[count] = real("1"); }

        if (i == l || expr[i] == '+' || expr[i] == '-') { b[count] = real("0"); }

        else if (++i == l || expr[i] != '^') { b[count] = real("1"); }

        else {

            string tmp;

            for (i++; i < l && expr[i] != '+' && expr[i] != '-'; i++) { tmp += expr[i]; }

            if (tmp.empty() == false && real::check(tmp) && tmp.back() != '-' && (b[count] = real(tmp)).point == 0) {}

            else { break; }

        }

    }

    if (i != l) { mark = false; return; }

    for (i = 1; i < number; i++)

    {

        if (b[i] <= b[i - 1] || a[i].zero()) { break; }

    }

    if (i != number) { mark = false; return; }

    mark = true;

}

void poly::operator=(const poly& that)

{

    number = that.number;

    a = new real[number]; b = new real[number];

    for (int i = 0; i < number; i++)

    {

        a[i] = that.a[i]; b[i] = that.b[i];

    }

}

void poly::print()const

{

    cout << "\nF(X)=";

    for (int i = number - 1; i > -1; i--) {

        if (a[i].sign == 1) { cout << "+"; }

        a[i].show(0); cout << "X^"; b[i].show(0);

    }

    cout << endl;

}

const complex poly::f(const complex& n)const

{

    complex sum("0","0");

    for (int i = 0; i < number; i++) {

        sum = sum + (a[i] * (n ^ b[i]));

    }

    return sum;

}

const real poly::f(const real& n)const

{

    real sum("0");

    for (int i = 0; i < number; i++) {

        sum = sum + (a[i] * (n ^ b[i]));

    }

    return sum;

}

poly* poly::df(size_t m)const

{

    poly* tmp = new poly;

    if (m == 0) {

        *tmp = *this;

        return tmp;

    }

    else {

        real n;

        while (m) { n.number += m % 10; m /= 10; }

        int count = 0;

        for (int i = 1; i < number; i++) {

            if (n == b[i] == false && n <= b[i]) { count++; }

        }

        tmp->number = count;

        tmp->a = new real[++tmp->number]; tmp->b = new real[tmp->number];

        for (int i = number - 1; i > 0; i--)

        {

            if (n <= b[i]) {

                tmp->a[count] = a[i] * (b[i].chooseandrank(n)); tmp->b[count] = (b[i] - n);

                count--;

            }

        }

        return tmp;

    }

}

poly::~poly()

{

    delete[]a;

    delete[]b;

    while (first) {

        node* q = first;

        first = first->next;

        delete (q->h);

        delete q;

    }

    number = 0;

    first = last = nullptr;

}

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值