#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