使用切比雪夫多项式,我们可以使用CGAL和CORE库精确计算sin(2 * Pi / n),如下面的代码:
#include <CGAL/CORE_Expr.h>
#include <CGAL/Polynomial.h>
#include <CGAL/number_utils.h>
//return sin(theta) and cos(theta) for theta = 2pi/n
static std::pair<AA, AA> sin_cos(unsigned short n) {
// We actually use -x instead of x since root_of will give the k-th
// smallest root but we want the second largest one without counting.
Polynomial x(CGAL::shift(Polynomial(-1), 1));
Polynomial twox(2*x);
Polynomial a(1), b(x);
for (unsigned short i = 2; i <= n; ++i) {
Polynomial c = twox*b - a;
a = b;
b = c;
}
a = b - 1;
AA cos = -CGAL::root_of(2, a.begin(), a.end());
AA sin = CGAL::sqrt(AA(1) - cos*cos);
return std::make_pair(sin, cos);
}
但是如果我想精确地计算sin(2 * m * Pi / n),其中m和n是整数,那么我应该使用多项式的公式是什么?感谢。
答案 0 :(得分:2)
(部分解决方案。)
这实质上是将统一根的实部和虚部计算为代数数。设表示w(m)= exp(2 * pi * I * m / n)。然后,w(m)本身是En(x)= x ^ n-1的复根。
您需要找到Re(w(m))的定义多项式。 Resultant是找到这样一个多项式的工具:2 * Re(w(m))是Res的根(En(x-y),En(y); y)。
为了解释为什么会这样:注意2 * Re(w(m))= w(m)+ conj(w(m)),并且En的复根来自共轭对;因此,conj(w(m))也是En的根。现在松散地说,En(y)部分“约束”y是En的任何(复数)根,并且将它与第一个参数组合允许x取任何复数值,使得x-y也是En的根。因此,可能的分配是y = conj(w(m))和xy = w(m),因此x = w(m)+ conj(w(m))= 2 * Re(w(m))。登记/>
CGAL可以计算多元多项式的结果,因此您可以计算此结果,并且您只需选择正确的实根。 (最大的一个显然是w(0)= 1,最小的一个是2 * Re(w(floor(n / 2)))。)
不幸的是,结果具有高复杂度(度数n ^ 2),并且结果计算将不是您见过的最快的运算。此外,您将支付密集多项式,尽管您的实例非常稀疏且结构化。因人而异;我对你的用例一无所知,如果你需要更高的学位
然而,我在计算机代数系统中做了一些测试,我发现结果分裂成更合理大小的因子,并且它的所有真实根实际上都属于更简单的度数底面多项式(n / 2)+1只要。 (没有证据,只是观察。)
我不知道写下这个因素的直接公式,我不想推测它。但也许有些人在mathoverflow或math.stackexchange可以提供帮助吗?
编辑:这是至少一个递归公式的猜测 我写s(n,x)得到包含所有实根但得到0的结果多项式的重要因子。这意味着s(n,x)具有m!= n /的所有值2 * Re(w(m)) 4,3 * n / 4作为根。
s(0,x)= 0
s(1,x)= x - 2
s(2,x)= x ^ 2 - 4
s(3,x)= x ^ 2 - x - 2
s(4,x)= x ^ 2 - 4
s(5,x)= x ^ 3 - x ^ 2 - 3 * x + 2
s(6,x)= x ^ 4 - 5 * x ^ 2 + 4
s(7,x)= x ^ 4 - x ^ 3 - 4 * x ^ 2 + 3 * x + 2
s(8,x)= x ^ 4 - 6 * x ^ 2 + 8
s(n,x)=(x ^ 2-2)* s(n-4,x) - s(n-8,x)
等待证明......