任务描述
编写程序实现一元多项式的除法计算,并输出计算后的商式多项式与余式多项式,多项式系数为整数或小数(精确度为小数点后4位)。
相关知识
一元多项式的除法计算,具体计算过程请参照课程内容。
其中:
多项式除法:输入的多项式为标准多项式,形如
ax^n+bx^(n-1)+...+cx+d(多项式按照指数降次方式表示)。
编程要求
实践中需要定义一个多项式类,该类支持标准多项式除法操作,计算出商式表达式和余式表达式。表达式前的系数均为整数或小数,多项式计算过程中,小数计算需按照系统默认浮点数精度先行计算(数据类型设置为float类型),最后计算完成时才截取4位数;
程序的输入为两行:第一行表示被除式,第二行表示除式;
程序的输出为两行:第一行为商式,第二行为余式。如果输入格式不满足要求,或不满足除法运算法则,则输出error。具体样例参照测试用例。
注意:
(1) 用户输入的合法表达式仅包含.,+,^,-符号和数字以及字母x,每一项之间用 +或- 隔开,每一项的指数为非负整数,系数为整数或小数,小数精度设置为小数点后4位(事实上,测试输入中系数不超过小数点后4位);
(2) 凡是输出中含有表达式的,都是标准形式并保留4位小数,例如输出格式为:1.0000x^2+1.0000;
(3) 输出的表达式中不带空格。
其中:
本例中不再测试输入表达式不正确的情形(即所输入的表达式均为标准形式且不含有错误)。
测试用例
测试输入:
2^2-5x-1
x-3
预期输出:
2.0000x+1.0000
2.0000
上述结果代表:(2x^2-5x-1)/(x-3)=(2x+1)余2。
测试输入:
x^3-3x^2-x-1
3x^2-2X+1
预期输出:
0.3333x-0.7777
-2.8888x-0.2222
若商式或余式系数不能整除,小数直接截位。
测试输入:
x^3-3x^2-x-1
0
预期输出:
error
error
被除式为0,不符合运算法则,输出两行error。
测试输入:
-1
-1
预期输出:
1.0000
0.0000
参考代码
exercise_2.cpp
#include "std_lib_facilities.h"
#include "Polynomial.h"
#include<cstring>
int main() {
//请打开文件目录修改Polynomial.h,Polynomial.cpp,和exercise_2.cpp
/********** Begin **********/
Polynomial p, ret;
bool exercise1 = false;
if (exercise1) {
//第一关执行代码
char str[2333];
scanf("%s", str);
bool pd = p.Scan(str);
if (!pd) {
printf("error\nerror\nerror\n");
return 0;
}
p.Print();
ret = p.Derivative();
ret.Print();
// puts("0.0000");
double x;
cin >> x;
p.cal(x);
} else {
//第二关执行代码
char str[2333];
scanf("%s", str);
for (int i = 0; i < strlen(str); ++i)
if (str[i] == 'X') str[i] = 'x';
p.Scan(str);
scanf("%s", str);
if (str[0] == '0' && strlen(str) == 1) {
printf("error\nerror");
return 0;
}
for (int i = 0; i < strlen(str); ++i)
if (str[i] == 'X') str[i] = 'x';
ret.Scan(str);
// printf("0.0000\n0.0000");
// ret.Print();
p.Div(ret);
}
/********** End **********/
return 0;
}
Polynomial.h
class Polynomial{
public:
float A[2333];
int n;
Polynomial();
bool Scan(char *);
void Print();
Polynomial Derivative();
void cal(float);
Polynomial Div(Polynomial v);
};
Polynomial.cpp
#include"Polynomial.h"
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#define double float
using namespace std;
Polynomial::Polynomial() {
memset(A, 0, sizeof A);
n = 0;
}
bool check(char ch) {
if (ch == '.') return true;
if (ch == '+') return true;
if (ch == '^') return true;
if (ch == '-') return true;
if (ch == 'x') return true;
if (ch <= '9' && ch >= '0') return true;
return false;
}
bool Polynomial::Scan(char * s) {
int len = strlen(s);
for (int i = 0; i < len; ++i)
if (!check(s[i]))
return false;
int pos[2333], tot = 0;
for (int i = 1; i < len; ++i)
if (s[i] == '+' || s[i] == '-')
pos[++tot] = i;
pos[++tot] = len;
int now = 0;
bool minus = false;
int cnt = 0;
while (now < len) {
if (cnt && pos[cnt + 1] == pos[cnt] + 1)
return false;
if (s[now] == '-')
minus = true, ++now;
else if (s[now] == '+')
minus = false, ++now;
int posx = -1, pospow = -1, posdot = -1;
for (int i = now; i < pos[cnt + 1]; ++i) {
if (posx == -1 && s[i] == 'x')
posx = i;
else if (s[i] == 'x')
return false;
if (pospow == -1 && s[i] == '^')
pospow = i;
else if (s[i] == '^')
return false;
if (posdot == -1 && s[i] == '.')
posdot = i;
else if (s[i] == '.')
return false;
}
if (posx == -1 && pospow > 0)
return false;
if (posx > 0 && posdot > posx)
return false;
if (posdot > 0 && posdot == now)
return false;
if (pospow > 0 && pospow < posx)
return false;
if (pospow > 0 && pospow + 1 == pos[cnt + 1])
return false;
int wei = -1;
if (posx < 0)
wei = 0;
else if (pospow < 0)
wei = 1;
else {
wei = 0;
for (int i = pospow + 1; i < pos[cnt + 1]; ++i) {
if (s[i] > '9' || s[i] < '0')
return false;
wei = wei * 10 + s[i] - '0';
}
}
if (n < wei)
n = wei;
double x = 0;
int endpos;
if (posx == -1)
endpos = pos[cnt + 1] - 1;
else
endpos = posx - 1;
if (posdot == -1) {
if (posx >= 0 && posx == now) x = 1;
else {
for (int i = now; i <= endpos; ++i) {
if (s[i] > '9' || s[i] < '0')
return false;
x = x * 10 + s[i] - '0';
}
}
} else {
for (int i = now; i < posdot; ++i) {
if (s[i] > '9' || s[i] < '0')
return false;
x = x * 10 + s[i] - '0';
}
double bas = 1;
for (int i = posdot + 1; i <= endpos; ++i) {
bas *= 0.1;
if (s[i] > '9' || s[i] < '0')
return false;
x = x + bas * (s[i] - '0');
}
}
if (minus) A[wei] -= x;
else A[wei] += x;
now = pos[++cnt];
}
return true;
}
void Polynomial::Print() {
bool printed = false;
for (int i = n; ~i; --i) {
if (abs(A[i]) < 1e-8) continue;
if (A[i] > 0 && printed) putchar('+');
printed = true;
string str = to_string(A[i]);
int cnt = 0;
bool dot = false;
for (int j = 0; j < str.size(); ++j) {
if (dot) ++cnt;
if (cnt > 4) break;
putchar(str[j]);
if (str[j] == '.') dot = true;
}
if (!dot) putchar('.'), cnt = 1;
while (cnt <= 4)
putchar('0'),
++cnt;
if (i) putchar('x');
if (i > 1) putchar('^'), cout << i;
}
if (!printed) printf("0.0000");
putchar('\n');
}
Polynomial Polynomial::Derivative() {
Polynomial ret;
ret.n = n - 1;
if (ret.n < 0) ret.n = 0;
for (int i = n; i; --i) {
ret.A[i - 1] = A[i] * i;
}
return ret;
}
void Polynomial::cal(double x) {
double ret = A[0];
double bas = 1;
for (int i = 1; i <= n; ++i) {
bas *= x;
ret += bas * A[i];
}
string str = to_string(ret);
int cnt = 0;
bool dot = false;
for (int j = 0; j < str.size(); ++j) {
if (dot) ++cnt;
if (cnt > 4) break;
putchar(str[j]);
if (str[j] == '.') dot = true;
}
if (!dot) putchar('.'), cnt = 1;
while (cnt <= 4)
putchar('0'),
++cnt;
}
Polynomial Polynomial::Div(Polynomial v) {
bool fuck = false;
for (int i = n; ~i; --i)
if (abs(A[i]) > 1e-8) fuck = true;
if (!fuck) {
printf("0.0000\n0.0000");
return v;
}
if (n < v.n) {
puts("0.0000");
Print();
return v;
}
Polynomial x, y;
y.n = n;
for (int i = n; ~i; --i)
y.A[i] = A[i];
x.n = n - v.n;
for (int i = x.n; ~i; --i) {
float tmp = y.A[i + v.n] / v.A[v.n];
if (abs(y.A[i + v.n]) < 1e-9 || abs(tmp) < 1e-9) continue;
x.A[i] = tmp;
y.A[i + v.n] = 0;
for (int j = i - 1; j - i + v.n >= 0; --j) {
if (abs(v.A[j - i + v.n]) <= 1e-8) continue;
y.A[j + v.n] -= v.A[j - i + v.n] * tmp;
}
}
x.Print();
y.Print();
return x;
}