【问题标题】:Find the coefficients of the polynomial given its roots在给定根的情况下找到多项式的系数
【发布时间】:2015-11-08 13:16:37
【问题描述】:

在给定n, x_1, ..., x_n, a(n) 的值的情况下,我正在尝试编写一个能找到a(0),..., a(n-1) 的算法,这样:

a(n)*p^n + a(n-1)*p^(n-1) + ... + a(1)*p + a(0) = a(n)(p-x_1)(p-x_2)...(p-x_n)

对于所有真正的 p。

在乘以 a(n)(p-x_1)(p-x_2) 之后,我想到了使用 Viete 的公式来找到系数。

但事实证明,写下代码并没有我想象的那么明显。

我只想在我的代码中使用基础知识——即循环、if-s 加法和乘法——没有现成/复杂的函数。

以下是公式:

首先,我想强调一下,我只需要一个伪代码,我并不关心为根和系数定义数组。这就是为什么我只写 a(n), xn。哦,如果我从 i=1 而不是 i=0 开始索引以便与数学符号同步,我希望它不会打扰您。为了从 i=0 开始,我必须重新枚举根并引入更多括号。

这就是我迄今为止想出的:

a(n-1)=0;
for(i=1; i <= n; i++){
    a(n-1) = a(n-1) + x_i;
}

a(n-1) = -a(n)*a(n-1);
a(n-2)=0;

for(i=1; i <= n; i++){ 
    for(j=i; j <= n; j++){
        a(n-2) = a(n-2)+ x_i * x_j;
    }
}

a(n-2) = -a(n)*a(n-2);
a(n-3)=0;

for(i=1; i <= n; i++){
    for(j=i; j <= n; j++){
        for(k=j; k <= n; k++){
            a(n-3) = a(n-3)+ x_i * x_j * x_k;
        }
    }
}

a(n-3) = a(n)*a(n-3);

...

a(0)=1;
for(i=1; i<=n; i++){
    a(0) = a(0) * x_i;
}
if(n%2 == 0) a(0) = a(n) * a(0);
else a(0) = -a(n) * a(0);

如你所见,它看起来不太好。

我想将所有这些循环链接到一个循环中,因为如果没有我无法编写完整的代码,我就无法填补 a(0) 和 a(n-j) 之间对于固定 j 的空白。

你能帮帮我吗?

根据 Nico Schertler 的回答,这就是我所拥有的:

for(i=1; i<=n; i++)
{a(i)=1; 
for(j=1; j <= n; j++)
{b(i)= clone( a(i) );
a(i) = a(i-1);
b(i) = x_j * b(i);
c(i) = a(i) - b(i);
}
}

如果换成我们写会不会一样

for(i=1; i<=n; i++)
{a(i)=1; b(i)=1;
for(j=1; j <= n; j++)
{t = a(i) ;
a(i) = a(i-1);
b(i) = x_j * t;
c(i) = a(i) - b(i);
}
}

(例如,这就是我们交换数组的两个元素的方式,方法是将 a[i] 的值保存在某个变量 t 中)。

【问题讨论】:

  • 你用哪种语言写作?当您说“如您所见,看起来不太好。”时,您是什么意思?算法是否按照您所写的那样工作?
  • @Gijs 我用 C++ 编写,所以应该有方括号 [ ] 而不是 ( )。但它看起来不太好,我的意思是我在下面一行中写的。准确地说,我从计算 a[n-1] 开始,然后是 a[n-2], ...,在某些时候我需要找到 a[2], a[1], a[0] 所以我需要从 a[n- something] 切换到 a[ something]
  • 如果根是整数,另一种可能不太实用但有趣的系数计算方法是一种称为 Kronecker substitution 的技术。

标签: algorithm loops for-loop polynomial-math polynomials


【解决方案1】:

您可以增量创建多项式。

p = 1 开头。 IE。 a(0) = 1.

为了添加一个根,您必须将当前多项式乘以x - x_i。这是:

p * (x - x_i) = p * x - p * x_i

所以需要支持三个操作:

1。乘以 x

这很简单。只需将所有系数向左移动一位即可。即

a(i    ) := a(i - 1)
a(i - 1) := a(i - 2)
...
a(1    ) := a(0)
a(0    ) := 0

2。乘以一个标量

这同样简单。将每个系数相乘:

a(i    ) *= s
a(i - 1) *= s
...

3。减法

只需减去各自的系数:

c(i    ) = a(i    ) - b(i    )
c(i - 1) = a(i - 1) - b(i - 1)
...

总共

按根添加根。首先,克隆您当前的多项式。然后,进行上述操作:

p := 1
for each root r
    p' = clone(p)
    multiply p with x
    multiply p' with r
    p := p - p'
next

【讨论】:

  • 谢谢。你能解释一下为什么我们取 p' = clone(p) 而不仅仅是 p' = p?
  • @Don 因为您需要将原始内容与某些内容相乘,而将克隆内容与其他内容相乘。
  • 当然,如果乘法没有发生在适当的位置,但无论如何都返回了一个副本,那么您不需要进行单独的克隆。
  • 如果我们只写会出现什么问题: p' := p;将 p 与 x 相乘;将 p' 与 r 相乘; p := p - p' ?
  • @Don 结果将是常数 0 多项式,因为最后您将执行 p := p - p
【解决方案2】:

用于此目的的 c# 中的静态函数。 x^4-11x^3+44x^2-76x+48 的根是 {2,2,3,4} 并给定参数

 roots = new Complex[4] {2, 2, 3, 4}

此函数返回 [48,-76,44,-11,1]

public static double[] FromRoots(Complex[] roots)
{
   int N = roots.Length;
   Complex[] coefs = new Complex[N + 1];
   coefs[0] = -roots[0];
   coefs[1] = 1.0;

   for (int k = 2; k <= N; k++)
   {
       coefs[k] = 1.0;
       for (int i = k - 2; i >= 0; i--)
       {
           coefs[i + 1] = coefs[i] - roots[k - 1] * coefs[i + 1];
       }
       coefs[0] *= -roots[k - 1];

       if (Math.IEEERemainder(k, 2) == 1)
           coefs[k] = -coefs[k];
    }

        double[] realCoefs = new double[N + 1];
        for (int i = 0; i < N + 1; i++)
            realCoefs[i] = coefs[i].Real; // Not sure about this part!

        return realCoefs;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 2023-01-09
    • 2016-07-07
    • 1970-01-01
    • 2014-01-06
    相关资源
    最近更新 更多