问题求解与实践-简单数值计算 第1关:一元多项式化简与求导

任务描述
编写程序实现对一元多项式的化简,求导以及求值。多项式系数为整数或小数,小数精度为小数点后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;
}

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值