ここでは、表記法を使用します
数値を計算してから定義を適用することで、数値の連分数を見つけることができますが、 0 、 a 1 ... a n を見つけるには少なくとも O(n) ビットのメモリが必要です。悪い。倍精度浮動小数点を使用すると、0、1 ... 19しか検出できません。
別の方法として、a,b,c が有理数である場合、1/(a+b*2 1/3 +c*2 2/3 ) = x +y*2 1/3 +z*2 2/3、つまり
したがって、ブースト有理ライブラリを使用して x、y、および z を絶対精度で表現すると、2 1/3 の倍精度のみを使用して正確に floor(x + y*2 1/3 + z*2 2/3 )を取得できます。 2 2/3は、真の値の 1/2 以内にあればよいためです。残念ながら、x、y、および z の分子と分母はかなり急速に大きくなり、代わりに通常の浮動小数点数を使用すると、エラーがすぐに積み重なっていきます。
このようにして、0、1 ... 10000を 1 時間以内に計算できましたが、どういうわけか mathematica は 2 秒でそれを実行できます。参照用の私のコードは次のとおりです
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
namespace mp = boost::multiprecision;
int main()
{
const double t_1 = 1.259921049894873164767210607278228350570251;
const double t_2 = 1.587401051968199474751705639272308260391493;
mp::cpp_rational p = 0;
mp::cpp_rational q = 1;
mp::cpp_rational r = 0;
for(unsigned int i = 1; i != 10001; ++i) {
double p_f = static_cast<double>(p);
double q_f = static_cast<double>(q);
double r_f = static_cast<double>(r);
uint64_t floor = p_f + t_1 * q_f + t_2 * r_f;
std::cout << floor << ", ";
p -= floor;
//std::cout << floor << " " << p << " " << q << " " << r << std::endl;
mp::cpp_rational den = (p * p * p + 2 * q * q * q +
4 * r * r * r - 6 * p * q * r);
mp::cpp_rational a = (p * p - 2 * q * r) / den;
mp::cpp_rational b = (2 * r * r - p * q) / den;
mp::cpp_rational c = (q * q - p * r) / den;
p = a;
q = b;
r = c;
}
return 0;
}