问题求解与实践-简单数值计算 第2关:一元多项式除法

任务描述
编写程序实现一元多项式的除法计算,并输出计算后的商式多项式与余式多项式,多项式系数为整数或小数(精确度为小数点后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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值