实验题目
多项式乘法问题
实验目的
设计一个一元稀疏多项式简单计算器
实验内容与要求
一元稀疏多项式简单计算器的基本功能是:
(1)输入并建立多项式;
(2)输出多项式,输出形式为整数序列:n,c1,e1,c2,e2,…,cn,en,其中n是多项式的项数,ci和ei分别是第i项的系数和指数,序列按指数降序排列。
(3)多项式a与多项式b相乘,建立多项式。
实验内容和实验步骤
1、实验构思和设计
本次实验是要建立一个多项式乘法,在写程序时,难点在于怎样存储这个多项式以及完成运算。
想到存储多项式,第一想法是用一个链表,这个链表包含系数和次数,但是构造链表容易,用这个链表进行多项式的乘法比较难想。其次是用数组,数组存放的思路是,数组的下标是多项式中某项的次数,数组的内容是该项的系数。
用数组的优点是,在进行乘法的时候,数组的下标可以直接相加,而数组的内容可以直接相乘,最后把结果存放在另一个新数组里。例如2x^2^*3x^3^
时,定义num1[2]=2,num2[3]=3
,这样相乘的结果就是num3[2+3]=num1[2]*num2[3]
怎样设计输入呢?输入的依次是系数,次数,存放的方式是用一个for循环,循环次数较多,最后说系数输入0结束,在for循环中用break跳出,代码如下
for (i = 0; i < 30; i++)
{
cin >> c1;
if(c1==0) break;
cin >> c;
num[c] = c1;
}
输入端就可以写
cout << "请输入多项式,输入格式依次为系数,次数,最后输入0结束" << endl;
还剩最后一个输出结果,一开始是写成这样的
for(int i=1; i<30; i++)
{
if(num3[i])
{
cout << num3[i] << "x^" << i << "+";
}
}
但是这段程序有一个很明显的问题,就是式子最后面会跟一个 + ,如何把后面的+去掉呢?
把代码更改为
int temp = 0;
for(int i=29; i>=0; i--)
{
if(num3[i] != 0)
{
if(temp && num3[i] > 0) {cout << "+";}
else if(num3[i] < 0) {cout << "-";}
if(num3[i]!=1)
printf("%d",(num3[i] > 0) ? num3[i]: -num3[i]);
cout << "x^" << i;
temp++;
}
}
成功解决,并且省略了系数为1的时候出现的那个“1”,同时考虑了1、输出要降序 2、系数为负数时怎样确定+ -符号,更符合数学逻辑
另外在相乘的时候,我一开始写的是
for (int i = 0; i <= 30; i++)//遍历一个乘数
{
if (num1[i] == 0) continue;
for (int j = 0; j <= 30; j++)//遍历第二个乘数
{
if (num2[j] == 0) continue;
num3[i + j] = num1[i] * num2[j];
}
}
但是调试发现,结果并不是正确的,调试了很久都没有想到问题出在哪里,最后才想到,问题就出在num3[i + j] = num1[i] * num2[j];
这一行,原因是如果相乘之后,应该把次数相等的项相加,但是这一行的意思是把重复出现的次数相等的项替换掉,加上一个+,即改成num3[i + j] += num1[i] * num2[j];
问题就解决了
当把所有代码写完后调试发现,忘了考虑了一个很重要的事情,次数也是有负数的,但是我把次数作为了数组的下标,数组下标是不能有负数了,我这里参考使用移码形式,把代码更改后解决了这个问题
2、最终结果
#include<iostream>
using namespace std;
void init(int* num)
{
int c, c1;
cout << "请输入多项式,输入格式依次为系数,次数,最后输入0结束" << endl;
for (int i = 0; i < 20; i++)
{
cin >> c1;
if (c1 == 0) break;
cin >> c;
num[c + 500] += c1;
}
}
void mu(int* num1, int* num2, int* num3)//多项式乘法
{
for (int i = 0; i <= 1000; i++)//遍历一个乘数
{
if (num1[i] == 0) continue;
for (int j = 0; j <= 1000; j++)
{
if (num2[j] == 0) continue;
num3[i + j - 500] += num1[i] * num2[j];//num3[i + j] = num1[i] * num2[j];
}
}
cout << "\n输出的结果为" << endl;
int temp = 0;
for (int i = 999; i >= 0; i--)
{
if (num3[i] != 0)
{
if (temp && num3[i] > 0) { cout << "+"; }
else if (num3[i] < 0) { cout << "-"; }
if (num3[i] != 1)
printf("%d", (num3[i] > 0) ? num3[i] : -num3[i]);
cout << "x^" << i - 500;
temp++;
}
}
}
int main()
{
int num[1000] = { 0 }, num2[1000] = { 0 }, num3[1000] = { 0 };
init(num);
init(num2);
mu(num, num2, num3);
return 0;
}
3、时空分析
由于最多是两层循环,循环的次数都是常数,故复杂度为O(1)
4、输入值的范围
输入的多项式最多为20项,系数为任意值,最后输出的多项式的次数在±500之间
5、实验用测试数据和相关结果分析
实验数据依次为(依次为系数,次数)
实验次数 | 第一个多项式 | 第二个多项式 |
---|---|---|
1 | 1 2 3 4 | 1 2 3 4 |
2 | -1 4 | 6 3 |
3 | 3 4 8 4 | 2 2 2 2 2 0 |
4 | -2 2 6 8 | 3 -5 8 9 5 -4 |
第一个是正常测试,第二个是系数为负数,第三个为有可以合并的项,且指数为0,看是否与结束的0混淆,第四个是指数带负数,经测试全部通过,测试结果如下: