Boost::multiprecision 如何使用 sqrt 和 ceil?
How to use sqrt and ceil with Boost::multiprecision?
您知道如何使用 Boost::multiprecison 正确无误地执行这一行简单的代码吗?
boost::multiprecision::cpp_int v, uMax, candidate;
//...
v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
使用 MSVC 存在 "sqrt" 错误,可以通过以下方式修复:
v += 6 * ceil((sqrt(static_cast<boost::multiprecision::cpp_int>(uMax * uMax - candidate)) - v) / 6);
然后 "ceil" 出现错误,可以通过以下方式修复:
namespace bmp = boost::multiprecision;
typedef bmp::number<bmp::cpp_dec_float<0>> float_bmp;
v += 6 * ceil(static_cast<float_bmp>((sqrt(static_cast<bmp::cpp_int>(uMax * uMax - candidate)) - v) / 6));
然后出现"generic interconvertion"!?!
的错误
我觉得应该有更优雅的方式来实现这么简单的一行代码,不是吗?
如果您对此有任何想法,请告诉我。
此致。
"problem"(它实际上是一个功能)是您正在使用启用了模板表达式的number<>
前端。
这意味着在编译器生成代码之前可以大大优化甚至消除许多操作。
你有两个选择:
分解事物
using BF = boost::multiprecision::cpp_bin_float_100;
using BI = boost::multiprecision::cpp_int;
BI v = 1, uMax = 9, candidate = 1;
//v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
BF tmp1(uMax * uMax - candidate);
BF tmp2(sqrt(tmp1) - BF(v));
BF tmp3(ceil(tmp2 / 6));
BI tmp4(tmp3.convert_to<BI>());
std::cout << tmp1 << " " << tmp2 << " " << tmp3 << " " << tmp4 << "\n";
v = v + 6*tmp4;
所以你可以写
v += 6*ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
通过强制评估表达式模板(以及使用 convert_to<>
从浮点数 -> 整数的潜在有损转换)来工作。
一般来说,您可以切换到以下类型的非表达式模板版本:
using BF = mp::number<mp::cpp_bin_float_100::backend_type, mp::et_off>;
using BI = mp::number<mp::cpp_int::backend_type, mp::et_off>;
在这种特殊情况下,它并没有太大变化,因为您仍然需要输入 "coercions" from integer -> float -> integer:
v += 6 * ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
通过简化,如果您将所有类型改为浮动(例如 cpp_dec_float),您可以摆脱这些复杂的人工制品:
using BF = mp::number<mp::cpp_dec_float_100::backend_type, mp::et_off>;
BF v = 1, uMax = 9, candidate = 1;
v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
CAVEAT Use your profiler to see that using et_off
doesn't cause a performance problem on your code-base
这是一个展示所有三种方法的演示程序:
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/number.hpp>
int main() {
namespace mp = boost::multiprecision;
//v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
{
using BF = mp::cpp_bin_float_100;
using BI = mp::cpp_int;
BI v = 1, uMax = 9, candidate = 1;
#ifdef DEBUG
BF tmp1(uMax * uMax - candidate);
BF tmp2(sqrt(BF(uMax * uMax - candidate)) - BF(v));
BF tmp3(ceil(tmp2 / 6));
BI tmp4(tmp3.convert_to<BI>());
std::cout << tmp1 << " " << tmp2 << " " << tmp3 << " " << tmp4 << "\n";
#endif
v += 6*ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
}
{
using BF = mp::number<mp::cpp_bin_float_100::backend_type, mp::et_off>;
using BI = mp::number<mp::cpp_int::backend_type, mp::et_off>;
BI v = 1, uMax = 9, candidate = 1;
v += 6 * ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
}
{
using BF = mp::number<mp::cpp_dec_float_100::backend_type, mp::et_off>;
BF v = 1, uMax = 9, candidate = 1;
v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
}
}
您知道如何使用 Boost::multiprecison 正确无误地执行这一行简单的代码吗?
boost::multiprecision::cpp_int v, uMax, candidate;
//...
v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
使用 MSVC 存在 "sqrt" 错误,可以通过以下方式修复:
v += 6 * ceil((sqrt(static_cast<boost::multiprecision::cpp_int>(uMax * uMax - candidate)) - v) / 6);
然后 "ceil" 出现错误,可以通过以下方式修复:
namespace bmp = boost::multiprecision;
typedef bmp::number<bmp::cpp_dec_float<0>> float_bmp;
v += 6 * ceil(static_cast<float_bmp>((sqrt(static_cast<bmp::cpp_int>(uMax * uMax - candidate)) - v) / 6));
然后出现"generic interconvertion"!?!
的错误我觉得应该有更优雅的方式来实现这么简单的一行代码,不是吗? 如果您对此有任何想法,请告诉我。
此致。
"problem"(它实际上是一个功能)是您正在使用启用了模板表达式的number<>
前端。
这意味着在编译器生成代码之前可以大大优化甚至消除许多操作。
你有两个选择:
分解事物
using BF = boost::multiprecision::cpp_bin_float_100; using BI = boost::multiprecision::cpp_int; BI v = 1, uMax = 9, candidate = 1; //v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6); BF tmp1(uMax * uMax - candidate); BF tmp2(sqrt(tmp1) - BF(v)); BF tmp3(ceil(tmp2 / 6)); BI tmp4(tmp3.convert_to<BI>()); std::cout << tmp1 << " " << tmp2 << " " << tmp3 << " " << tmp4 << "\n"; v = v + 6*tmp4;
所以你可以写
v += 6*ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
通过强制评估表达式模板(以及使用
convert_to<>
从浮点数 -> 整数的潜在有损转换)来工作。一般来说,您可以切换到以下类型的非表达式模板版本:
using BF = mp::number<mp::cpp_bin_float_100::backend_type, mp::et_off>; using BI = mp::number<mp::cpp_int::backend_type, mp::et_off>;
在这种特殊情况下,它并没有太大变化,因为您仍然需要输入 "coercions" from integer -> float -> integer:
v += 6 * ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
通过简化,如果您将所有类型改为浮动(例如 cpp_dec_float),您可以摆脱这些复杂的人工制品:
using BF = mp::number<mp::cpp_dec_float_100::backend_type, mp::et_off>; BF v = 1, uMax = 9, candidate = 1; v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
CAVEAT Use your profiler to see that using
et_off
doesn't cause a performance problem on your code-base
这是一个展示所有三种方法的演示程序:
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/number.hpp>
int main() {
namespace mp = boost::multiprecision;
//v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
{
using BF = mp::cpp_bin_float_100;
using BI = mp::cpp_int;
BI v = 1, uMax = 9, candidate = 1;
#ifdef DEBUG
BF tmp1(uMax * uMax - candidate);
BF tmp2(sqrt(BF(uMax * uMax - candidate)) - BF(v));
BF tmp3(ceil(tmp2 / 6));
BI tmp4(tmp3.convert_to<BI>());
std::cout << tmp1 << " " << tmp2 << " " << tmp3 << " " << tmp4 << "\n";
#endif
v += 6*ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
}
{
using BF = mp::number<mp::cpp_bin_float_100::backend_type, mp::et_off>;
using BI = mp::number<mp::cpp_int::backend_type, mp::et_off>;
BI v = 1, uMax = 9, candidate = 1;
v += 6 * ceil((sqrt(BF(uMax * uMax - candidate)) - BF(v)) / 6).convert_to<BI>();
}
{
using BF = mp::number<mp::cpp_dec_float_100::backend_type, mp::et_off>;
BF v = 1, uMax = 9, candidate = 1;
v += 6 * ceil((sqrt(uMax * uMax - candidate) - v) / 6);
}
}