使用 Boost 计算 Champernowne 常数 C10
Calculating Champernowne constant C10 using Boost
我正在尝试使用以下公式计算 Champernowne constant C10:
在上面的公式中,我用b代替10来计算C10。我希望能够使用 Boost 的 cpp_dec_float
.
计算任意精度的常量
这是我的代码:
#include <boost/multiprecision/cpp_dec_float.hpp>
const long long PRECISION = 100;
typedef boost::multiprecision::number<
boost::multiprecision::cpp_dec_float<PRECISION> > arbFloat;
arbFloat champernowne()
{
arbFloat c, sub, n, k;
std::string precomp_c, postcomp_c;
for(n = 1; n == 1 || precomp_c != postcomp_c; ++n) {
for(k = 1; k <= n; ++k) {
sub += floor(log10(k));
}
precomp_c = static_cast<std::string>(c);
c += n / pow(10, n + sub);
postcomp_c = static_cast<std::string>(c);
}
return c;
}
这是代码的细分:
我首先定义一个精度为 100 位的变量 arbFloat
(这经常更改 — 所以我不想使用 cpp_dec_float_100
)。
公式有两个求和块,所以我用两个for循环来实现它们。在最里面的 for 循环中,我计算以 k = 1
开始的总和,条件是 k <= n
for floor(log10(k))
.
我已验证在 cpp_dec_float
returns 变量上使用 floor()
和 log10()
具有正确的精度。
- 因为最外层的求和一直到无穷大,我不得不在某个时候停止计算。为了检查是否超出精度,我在计算
c += n / pow(10, n + sub)
之前将 c
转换为字符串 - 然后在计算后将其转换为字符串。如果字符串相同,我结束计算,因为超过了精度(进一步的计算将是多余的)。
我也使用这个设置(通过字符串转换和比较来检查超出的精度)来计算其他变量 - 它工作得很好。
- 接下来我计算
c += n / pow(10, n + sub)
的最外层总和 - 以这种方式使用 pow()
是否保持精度。最后,我returnc
.
当我运行这个程序时,我得到以下变量:
0.1234567891001100120001300001400000150000001600000001700000000180000000001900000000002000000000000210
对比real Champerowne 常量 C10:
0.1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253546
只有前11位数字是正确的,其余的都不正确。我无法找到我要去哪里错了。我尝试了以下方法:
尝试用 c += n / pow(static_cast<arbFloat>(10), n + sub)
替换 c += n / pow(10, n + sub)
以检查 pow()
是否没有保持精度 - 但它没有改变任何东西。
尝试用将 log10(k)
转换为字符串和 "rounding" 字符串的方法替换 floor()
(仅保留 .
之前的字符)-但它没有改变任何东西。
尝试将 k <= n
更改为 k < n
、k <= n + 1
- 以防万一我误解了总和 - 但这只会使它更加不准确。
如果我需要解释更多,请告诉我。任何帮助将不胜感激!
sub 的前一个值在每次迭代中被结转;在循环内声明它。
arbFloat champernowne() {
arbFloat c;
for (int n = 1;; ++n) {
arbFloat sub;
for (int k = 1; k <= n; ++k) {
sub += floor(log10(k));
}
arbFloat const last = c;
c += n / pow(10, n + sub);
if (c == last) {
break;
}
}
return c;
}
我正在尝试使用以下公式计算 Champernowne constant C10:
在上面的公式中,我用b代替10来计算C10。我希望能够使用 Boost 的 cpp_dec_float
.
这是我的代码:
#include <boost/multiprecision/cpp_dec_float.hpp>
const long long PRECISION = 100;
typedef boost::multiprecision::number<
boost::multiprecision::cpp_dec_float<PRECISION> > arbFloat;
arbFloat champernowne()
{
arbFloat c, sub, n, k;
std::string precomp_c, postcomp_c;
for(n = 1; n == 1 || precomp_c != postcomp_c; ++n) {
for(k = 1; k <= n; ++k) {
sub += floor(log10(k));
}
precomp_c = static_cast<std::string>(c);
c += n / pow(10, n + sub);
postcomp_c = static_cast<std::string>(c);
}
return c;
}
这是代码的细分:
我首先定义一个精度为 100 位的变量
arbFloat
(这经常更改 — 所以我不想使用cpp_dec_float_100
)。公式有两个求和块,所以我用两个for循环来实现它们。在最里面的 for 循环中,我计算以
k = 1
开始的总和,条件是k <= n
forfloor(log10(k))
.
我已验证在 cpp_dec_float
returns 变量上使用 floor()
和 log10()
具有正确的精度。
- 因为最外层的求和一直到无穷大,我不得不在某个时候停止计算。为了检查是否超出精度,我在计算
c += n / pow(10, n + sub)
之前将c
转换为字符串 - 然后在计算后将其转换为字符串。如果字符串相同,我结束计算,因为超过了精度(进一步的计算将是多余的)。
我也使用这个设置(通过字符串转换和比较来检查超出的精度)来计算其他变量 - 它工作得很好。
- 接下来我计算
c += n / pow(10, n + sub)
的最外层总和 - 以这种方式使用pow()
是否保持精度。最后,我returnc
.
当我运行这个程序时,我得到以下变量:
0.1234567891001100120001300001400000150000001600000001700000000180000000001900000000002000000000000210
对比real Champerowne 常量 C10:
0.1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253546
只有前11位数字是正确的,其余的都不正确。我无法找到我要去哪里错了。我尝试了以下方法:
尝试用
c += n / pow(static_cast<arbFloat>(10), n + sub)
替换c += n / pow(10, n + sub)
以检查pow()
是否没有保持精度 - 但它没有改变任何东西。尝试用将
log10(k)
转换为字符串和 "rounding" 字符串的方法替换floor()
(仅保留.
之前的字符)-但它没有改变任何东西。尝试将
k <= n
更改为k < n
、k <= n + 1
- 以防万一我误解了总和 - 但这只会使它更加不准确。
如果我需要解释更多,请告诉我。任何帮助将不胜感激!
sub 的前一个值在每次迭代中被结转;在循环内声明它。
arbFloat champernowne() {
arbFloat c;
for (int n = 1;; ++n) {
arbFloat sub;
for (int k = 1; k <= n; ++k) {
sub += floor(log10(k));
}
arbFloat const last = c;
c += n / pow(10, n + sub);
if (c == last) {
break;
}
}
return c;
}