我写了这段代码来生成平方根N的连续分数。
但是当N = 139时失败。
输出应为{11,1,3,1,3,7,1,1,2,11,2,1,1,7,3,1,3,1,22}
虽然我的代码为我提供了394个术语的序列……其中前几个术语是正确的,但是当它达到22个时,它给出了12个!
有人可以帮我吗?
vector <int> f;
int B;double A;
A = sqrt(N*1.0);
B = floor(A);
f.push_back(B);
while (B != 2 * f[0])) {
A = 1.0 / (A - B);
B =floor(A);
f.push_back(B);
}
f.push_back(B);
最佳答案
根本问题是您不能将非平方的平方根精确地表示为浮点数。
如果ξ
是精确值,而x
是近似值(假定仍然相当好,因此特别是floor(ξ) = a = floor(x)
仍然成立),则继续分数算法的下一步骤后的差为
ξ' - x' = 1/(ξ - a) - 1/(x - a) = (x - ξ) / ((ξ - a)*(x - a)) ≈ (x - ξ) / (ξ - a)^2
因此,我们看到,由于
0 < ξ - a < 1
,所以逼近和实际值之间的差的绝对值会增加。每当出现较大的部分商(ξ - a
接近0)时,差异就会增加很大的比例。一旦差的(绝对值)为1或更大,就可以保证下一个计算出的部分商是错误的,但是第一个错误的部分商很可能会更早出现。Charles mentioned使用
n
正确数字的原始近似值,您可以计算出连续分数的n
部分商。这是一个很好的经验法则,但是正如我们看到的那样,任何大的部分商的成本都更高,从而减少了可获得的部分商的数量,并且有时您会更早地得到错误的部分商。√139
的情况是一个周期相对较长且带有几个较大的部分商的情况,因此第一个错误计算的部分商在周期结束之前出现就不足为奇了(我很惊讶它没有更早出现) 。使用浮点算法,无法避免这种情况。
但是对于二次波动,我们可以仅使用整数算术来避免该问题。假设您要计算的连续分数扩展
ξ = (√D + P) / Q
其中
Q
将D - P²
除以D > 1
并不是一个完美的正方形(如果不满足除数条件,您可以将D
替换为D*Q²
,将P
替换为P*Q
,将Q
替换为Q²
;您的情况为P = 0, Q = 1
,这是平凡的满足条件)。将完整的商写为ξ_k = (√D + P_k) / Q_k (with ξ_0 = ξ, P_0 = P, Q_0 = Q)
并表示部分商
a_k
。然后ξ_k - a_k = (√D - (a_k*Q_k - P_k)) / Q_k
并且,使用
P_{k+1} = a_k*Q_k - P_k
,ξ_{k+1} = 1/(ξ_k - a_k) = Q_k / (√D - P_{k+1}) = (√D + P_{k+1}) / [(D - P_{k+1}^2) / Q_k],
Q_{k+1} = (D - P_{k+1}^2) / Q_k
,因为P_{k+1}^2 - P_k^2
是Q_k
的倍数,所以归纳法Q_{k+1}
是整数,Q_{k+1}
除以D - P_{k+1}^2
。当且仅当
ξ
是二次波动,并且当上述算法中的第一对ξ
重复时,周期才结束,实数(P_k, Q_k)
的连续分数扩展是周期性的。纯平方根的情况特别简单,当Q_k = 1
的第一个k > 0
和P_k, Q_k
始终为非负数时,该时间段就完成了。使用
R = floor(√D)
,可以将部分商计算为a_k = floor((R + P_k) / Q_k)
因此上述算法的代码变为
std::vector<unsigned long> sqrtCF(unsigned long D) {
// sqrt(D) may be slightly off for large D.
// If large D are expected, a correction for R is needed.
unsigned long R = floor(sqrt(D));
std::vector<unsigned long> f;
f.push_back(R);
if (R*R == D) {
// Oops, a square
return f;
}
unsigned long a = R, P = 0, Q = 1;
do {
P = a*Q - P;
Q = (D - P*P)/Q;
a = (R + P)/Q;
f.push_back(a);
}while(Q != 1);
return f;
}
可以轻松计算周期长度为182的
√7981
的连续分数。关于c++ - 生成平方根的连续分数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12182701/