整数可用于存储单个数字,但不能用于存储数学表达式。例如,假设我有以下表达式:
6x ^ 2 + 5x + 3
我如何存储多项式?我可以创建自己的对象,但我不知道如何通过成员数据表示多项式。我不想创建一个函数来评估传入的参数,因为我不仅要评估它,还需要操作表达式。
向量是我唯一的选择还是有更合适的解决方案?
答案 0 :(得分:7)
一种简单而低效的方法是将其存储为系数列表。例如,问题中的多项式如下所示:
[6, 5, 3]
如果缺少某个术语,请在其位置放置零。例如,多项式2x^3 - 4x + 7
将表示如下:
[2, 0, -4, 7]
多项式的次数由列表的长度减去1给出。这种表示有一个严重的缺点:对于稀疏多项式,列表将包含很多零。
稀疏多项式的术语列表的更合理的表示是非零项的列表,其中每个项是包含该项的顺序和该顺序的系数的列表;多项式的次数由第一项的顺序给出。例如,多项式x^100+2x^2+1
将由此列表表示:
[[100, 1], [2, 2], [0, 1]]
作为这种表示有用的一个例子,本书SICP使用上述多项式的第二种表示法构建了一个简单但非常有效的symbolic algebra system。
答案 1 :(得分:2)
列表不是唯一的选择。
您可以使用映射(字典)将指数映射到相应的系数。
使用地图,您的示例将是
{2: 6, 1: 5, 0: 3}
(系数,指数)对的列表是非常标准的。如果你知道你的多项式是密集的,也就是说,所有的指数位置都是0到一些小的最大指数的小整数,你可以使用数组,正如我看到ÓscarLopez刚发布的那样。 :)
答案 2 :(得分:2)
您可以将表达式表示为表达式树。请参阅示例.NET Expression Trees。
这允许比简单多项式更复杂的表达式,并且这些表达式也可以使用多个变量。
在.NET中,您可以将表达式树操作为树,并且可以将其作为函数进行评估。
Expression<Func<double,double>> polynomial = x => (x * x + 2 * x - 1);
double result = polynomial.Compile()(23.0);
答案 3 :(得分:1)
面向对象的方法会说Polynomial是Monomials的集合,Monomial将系数和指数封装在一起。
当你有这样的多项式时,这种方法有效:
y(x) = x^1000 + 1
将数据结构与多项式顺序联系起来的方法对于这种病态情况来说非常浪费。
答案 4 :(得分:0)
Vector / array是显而易见的选择。根据表达式的类型,您可以考虑某种稀疏矢量类型(自定义,即基于字典甚至链表,如果表达式具有2-3个非零系数5x ^ 100 + x)。
在任何一种情况下,通过自定义类/接口进行公开都是有益的,因为您可以在以后替换实现。如果您打算编写大量的表达式操作代码,您可能希望提供标准操作(+, - ,*,equals)。
答案 5 :(得分:0)
您需要存储两件事:
在标准C ++中,“std :: vector&lt;&gt;”和“std :: list&lt;&gt;”可以做到这两点。
答案 6 :(得分:0)
只需将系数存储在数组或向量中即可。例如,在C ++中,如果您只使用整数系数,则可以使用std::vector<int>
,或使用实数std::vector<double>
。然后,您只需按顺序推动系数,并通过变量指数编号访问它们。
例如(再次在C ++中),要存储5 * x ^ 3 + 9 * x - 2,您可以这样做:
std::vector<int> poly;
poly.push_back(-2); // x^0, acceesed with poly[0]
poly.push_back(9); // x^1, accessed with poly[1]
poly.push_back(0); // x^2, etc
poly.push_back(5); // x^3, etc
如果你有大的,稀疏的多项式,那么你可能想要使用地图而不是矢量。如果你有固定大小的长度,那么你可能使用固定长度的数组而不是矢量。
我使用C ++作为示例,但同样的方案可以用于任何语言。
答案 7 :(得分:0)
您还可以将其转换为reverse Polish notation:
6x ^ 2 + 5x + 3 - &gt; x 2 ^ 6 * x 5 * + 3 +
其中x
和数字被“推”到堆栈上,操作(^,*,+)从堆栈中取出两个最顶层的值,并用操作的结果替换它们。最后,您可以在堆栈上获得结果值。
在这种形式下,很容易计算出任意复杂的表达式。
此表示也接近表达式的树表示,其中非叶树节点表示操作和函数,叶节点表示常量和变量。
树的好处在于,您还可以轻松地评估表达式,还可以对它们进行符号区分等操作。两者都具有递归性质。