任务描述
编写程序实现对一元多项式的化简,求导以及求值。多项式系数为整数或小数,小数精度为小数点后4位(直接截位方式),浮点数数据类型设定为double。
相关知识
一元多项式化简、求导与求值。
其中:
化简:例如输入为2+3x+5x+6x^2 则化简为多项式(按指数递减)的标准形式6.0000x^2+8.0000x+2.0000;
求导:x^n(n为非负整数)的一阶导数为n*x^(n-1),6x^2+8x+2求导为12.0000x+8.0000;
求值:给定x=0,则6x^2+8x+2值为2.0000。
编程要求
实践中需要定义一个多项式类Polynomial,该类支持如下操作:
根据用户输入的表达式初始化一个多项式并将其化简为标准形式,系数的精度设为小数点后4位(本题中,所有输出中的系数均为小数点后4位的形式);
对简化后的多项式进行求导,并按照多项式指数递降方式排列;
对多项式进行计算(多项式计算过程中,小数计算需要按照系统默认浮点数精度先行计算,最后计算完成时才截取位数)。
main函数中,用户提供输入、输出如下:
程序的输入为两行:第一行为多项式表达式,第二行为数值;
程序的输出为三行:第一行为进行化简后的多项式,第二行为多项式的导,第三行为多项式计算结果。如果输入格式不满足要求,则输出error。
注意:
(1) 用户输入的合法表达式仅包含.,+,^,-符号和数字以及字母x,每一项之间用 +或- 隔开,每一项的指数为非负整数,系数为整数或小数,小数精度设置为小数点后4位(事实上,测试输入中系数不超过小数点后4位)。
(2) 若只有一位常数项,求导为0,输出为0.0000。
(3) 输出的表达式中不带空格。
(4) 对double小数的截位,可以通过to_string将其转换为字符串并进行截位。请自行设计相应函数。
提示:在右侧可以切换文件。
测试说明
测试输入:
3x+5?
0
预期输出:
error
error
error
测试输入:
3x+4x+5x^2+1
0.1
预期输出:
5.0000x^2+7.0000x+1.0000
10.0000x+7.0000
1.7500
测试输入:
3x+2+5.1
1
预期输出:
3.0000x+7.1000
3.0000
10.1000
参考代码
src/step1/exercise_2.cpp
#include "std_lib_facilities.h"
#include "Polynomial.h"
int main() {
//请打开文件目录修改Polynomial.h,Polynomial.cpp,和exercise_2.cpp
/********** Begin **********/
Polynomial p, ret;
bool exercise1 = true;
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 {
//第二关执行代码
}
/********** End **********/
return 0;
}
src/step1/Polynomial.h
class Polynomial{
public:
double A[2333];
int n;
Polynomial();
bool Scan(char *);
void Print();
Polynomial Derivative();
void cal(double);
};
src/step1/Polynomial.cpp
#include"Polynomial.h"
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
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 (A[i] == 0) 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;
}