提高多精度舍入到 0
Boost multiprecision rounding towards 0
下面的代码使用 VC++ 在 Windows 上编译得很好:
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
namespace mp = boost::multiprecision;
using BigFloat = mp::cpp_dec_float_50;
using BigInt = mp::uint256_t;
template <int decimals = 0, typename T> T floorBI(T const& v)
{
static const T scale = pow(T(10), decimals);
if (v.is_zero())
return v;
// ceil/floor is found via ADL and uses expression templates for
// optimization
if (v < 0)
return ceil(v * scale) / scale;
else
// floor is found via ADL and uses expression templates for optimization
return floor(v * scale) / scale;
}
int main()
{
BigFloat A = 3;
BigFloat B = 2;
static_cast<BigInt>(floorBI<0>(static_cast<BigFloat>(A) / static_cast<BigFloat>(B)));
return 0;
}
,但是使用 GCC(对于 Android 和 iOS)
模板似乎有问题。
'should' 匹配的模板的特定错误读取
..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: could not match 'expression' against 'number'
UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
^
..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: could not match 1 against 0
..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: requirement 'boost::multiprecision::number_category<boost::multiprecision::backends::cpp_int_backend<256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value == number_kind_floating_point' was not satisfied [with Backend = boost::multiprecision::backends::cpp_int_backend<256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>]
..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: could not match 1 against 0
VC++ 处理所有这些 'just fine'.
期待@Sehe的到来;]
就像很多人已经建议的那样,表达式模板是罪魁祸首:
T推导为
boost::multiprecision::detail::expression<
boost::multiprecision::detail::divides,
boost::multiprecision::number<
boost::multiprecision::backends::cpp_dec_float<50>>,
boost::multiprecision::detail::expression<
boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<
boost::multiprecision::backends::cpp_dec_float<50>>,
boost::multiprecision::number<
boost::multiprecision::backends::cpp_dec_float<50>>,
void, void>,
void, void>
不能从 int 构造:T(10)
。相反,要么强制类型:
std::cout << floorBI<0>(BigFloat(A / (B * C))) << "\n";
或者更聪明地推导类型。
演示
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/number.hpp>
#include <iostream>
namespace bmp = boost::multiprecision;
using BigFloat = bmp::cpp_dec_float_50;
template <int decimals = 0, typename T>
std::enable_if_t<not bmp::is_number_expression<T>::value, T>
floorBI(T const& v)
{
static const T scale = pow(T(10), decimals);
if (v.is_zero())
return v;
// ceil/floor is found via ADL and uses expression templates for
// optimization
if (v < 0)
return ceil(v * scale) / scale;
else
// floor is found via ADL and uses expression templates for optimization
return floor(v * scale) / scale;
}
template <int decimals = 0, typename Expr>
auto floorBI(Expr const& expr,
std::enable_if_t<bmp::is_number_expression<Expr>::value, void>* enable = nullptr)
{
return floorBI<decimals, typename Expr::result_type>(expr);
}
int main()
{
BigFloat A(3), B(2), C(2);
std::cout << floorBI<1>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<1>(A / (B * C)) << "\n";
std::cout << floorBI<2>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<2>(A / (B * C)) << "\n";
B *= -1;
std::cout << floorBI<1>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<1>(A / (B * C)) << "\n";
std::cout << floorBI<2>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<2>(A / (B * C)) << "\n";
}
版画
0.7
0.7
0.75
0.75
-0.7
-0.7
-0.75
-0.75
下面的代码使用 VC++ 在 Windows 上编译得很好:
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
namespace mp = boost::multiprecision;
using BigFloat = mp::cpp_dec_float_50;
using BigInt = mp::uint256_t;
template <int decimals = 0, typename T> T floorBI(T const& v)
{
static const T scale = pow(T(10), decimals);
if (v.is_zero())
return v;
// ceil/floor is found via ADL and uses expression templates for
// optimization
if (v < 0)
return ceil(v * scale) / scale;
else
// floor is found via ADL and uses expression templates for optimization
return floor(v * scale) / scale;
}
int main()
{
BigFloat A = 3;
BigFloat B = 2;
static_cast<BigInt>(floorBI<0>(static_cast<BigFloat>(A) / static_cast<BigFloat>(B)));
return 0;
}
,但是使用 GCC(对于 Android 和 iOS) 模板似乎有问题。
'should' 匹配的模板的特定错误读取
..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: could not match 'expression' against 'number' UNARY_OP_FUNCTOR(ceil, number_kind_floating_point) ^ ..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: could not match 1 against 0 ..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: requirement 'boost::multiprecision::number_category<boost::multiprecision::backends::cpp_int_backend<256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void> >::value == number_kind_floating_point' was not satisfied [with Backend = boost::multiprecision::backends::cpp_int_backend<256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>] ..\boost/multiprecision/detail/default_ops.hpp:3745:18: note: candidate template ignored: could not match 1 against 0
VC++ 处理所有这些 'just fine'.
期待@Sehe的到来;]
就像很多人已经建议的那样,表达式模板是罪魁祸首:
T推导为
boost::multiprecision::detail::expression<
boost::multiprecision::detail::divides,
boost::multiprecision::number<
boost::multiprecision::backends::cpp_dec_float<50>>,
boost::multiprecision::detail::expression<
boost::multiprecision::detail::multiply_immediates,
boost::multiprecision::number<
boost::multiprecision::backends::cpp_dec_float<50>>,
boost::multiprecision::number<
boost::multiprecision::backends::cpp_dec_float<50>>,
void, void>,
void, void>
不能从 int 构造:T(10)
。相反,要么强制类型:
std::cout << floorBI<0>(BigFloat(A / (B * C))) << "\n";
或者更聪明地推导类型。
演示
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/number.hpp>
#include <iostream>
namespace bmp = boost::multiprecision;
using BigFloat = bmp::cpp_dec_float_50;
template <int decimals = 0, typename T>
std::enable_if_t<not bmp::is_number_expression<T>::value, T>
floorBI(T const& v)
{
static const T scale = pow(T(10), decimals);
if (v.is_zero())
return v;
// ceil/floor is found via ADL and uses expression templates for
// optimization
if (v < 0)
return ceil(v * scale) / scale;
else
// floor is found via ADL and uses expression templates for optimization
return floor(v * scale) / scale;
}
template <int decimals = 0, typename Expr>
auto floorBI(Expr const& expr,
std::enable_if_t<bmp::is_number_expression<Expr>::value, void>* enable = nullptr)
{
return floorBI<decimals, typename Expr::result_type>(expr);
}
int main()
{
BigFloat A(3), B(2), C(2);
std::cout << floorBI<1>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<1>(A / (B * C)) << "\n";
std::cout << floorBI<2>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<2>(A / (B * C)) << "\n";
B *= -1;
std::cout << floorBI<1>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<1>(A / (B * C)) << "\n";
std::cout << floorBI<2>(BigFloat(A / (B * C))) << "\n";
std::cout << floorBI<2>(A / (B * C)) << "\n";
}
版画
0.7
0.7
0.75
0.75
-0.7
-0.7
-0.75
-0.75