繁体   English   中英

提高多精度舍入到 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),模板似乎存在问题。

“应该”匹配的模板的特定错误读取

..\boost/multiprecision/detail/default_ops.hpp:3745:18: 注意:候选模板被忽略:无法将“expression”与“number”匹配.hpp:3745:18: 注意:候选模板被忽略:无法匹配 1 与 0..\boost/multiprecision/detail/default_ops.hpp:3745:18: 注意:候选模板被忽略:要求 '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' 不满足 [with Backend = boost::multiprecision::backends::cpp_int_backend<256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, 无效>]..\boost/multiprecision/detail/default_ops.hpp:3745:18 : 注意:候选模板被忽略:无法将 1 与 0 匹配

VC++ 可以“很好地”处理所有这些。

等待@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";

或者更聪明地推导类型。

示范

生活在 Coliru

#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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM