C++ 查找浮点类型在不丢失精度的情况下可以处理的最大整数大小

C++ 查找浮点类型在不丢失精度的情况下可以处理的最大整数大小,c++,floating-point,double,precision,C++,Floating Point,Double,Precision,Double的范围大于64位整数,但由于其表示形式,其精度较低(因为Double也是64位的,所以它不能适应更多的实际值)。因此,当表示较大的整数时,整数部分的精度开始下降 #include <boost/cstdint.hpp> #include <limits> template<typename T, typename TFloat> void maxint_to_double() { T i = std::numeric_limits<

Double的范围大于64位整数,但由于其表示形式,其精度较低(因为Double也是64位的,所以它不能适应更多的实际值)。因此,当表示较大的整数时,整数部分的精度开始下降

#include <boost/cstdint.hpp>
#include <limits>

template<typename T, typename TFloat>
void
maxint_to_double()
{
    T i = std::numeric_limits<T>::max();
    TFloat d = i;
    std::cout
        << std::fixed
        << i << std::endl
        << d << std::endl;
}

int
main()
{
    maxint_to_double<int, double>();
    maxint_to_double<boost::intmax_t, double>();
    maxint_to_double<int, float>();
    return 0;
}
请注意,max
int
如何在不损失精度的情况下装入
双精度
,而
boost::intmax\u t
(本例中为64位)无法装入
float
甚至不能保存
int

现在,问题是:C++中有没有一种方法来检查给定整数类型的整个范围是否可以适合于一个浮点类型而不会丢失精度?

最好

  • 这将是一个编译时检查,可以在静态断言中使用
  • 并且不涉及枚举编译器应该知道或可以计算的常量

您可以使用
std::numeric\u limits::digits
了解您的二进制精度。e、 g:

int binary_digits_double = numeric_limits<double>::digits;       // 53
int binary_digits_long_long = numeric_limits<long long>::digits; // 63
int binary_digits_uint = numeric_limits<unsigned int>::digits;   // 32
int binary\u digits\u double=数字限制::数字;//53
int binary_digits_long_long=数值限制::数字;//63
int binary\u digits\u uint=数值限制::digits;//32

只是一个小小的谓词:

#include <limits>

template <typename T, typename U>
struct can_fit
{
    static const bool value = std::numeric_limits<T>::digits
                            <= std::numeric_limits<U>::digits;
};

#include <iostream>

int main(void)
{
    std::cout << std::boolalpha;

    std::cout << can_fit<short, float>::value << std::endl;
    std::cout << can_fit<int, float>::value << std::endl;

    std::cout << can_fit<int, double>::value << std::endl;
    std::cout << can_fit<long long, double>::value << std::endl;

    std::cout << can_fit<short, int>::value << std::endl;
    std::cout << can_fit<int, short>::value << std::endl;
}

你为什么要检查?整数部分有52位精度,因此你得到多少。一旦你确定了极限,你就不能定义一个const?@比利:技术上C++不需要IEEE 754浮点,所以假设实现使用IEEE 754不是可移植的(尽管IEEE 754无处不在)。我已经更新了这个问题。我正在使用VC,这就是为什么我的答案中会出现
long
,尽管它还不是标准答案。
long
也被GCC和ICC接受。我相信DMC和其他一些公司也会这样做。这是一个非常常见的扩展,至少比使用int64要好。
#include <limits>

template <typename T, typename U>
struct can_fit
{
    static const bool value = std::numeric_limits<T>::digits
                            <= std::numeric_limits<U>::digits;
};

#include <iostream>

int main(void)
{
    std::cout << std::boolalpha;

    std::cout << can_fit<short, float>::value << std::endl;
    std::cout << can_fit<int, float>::value << std::endl;

    std::cout << can_fit<int, double>::value << std::endl;
    std::cout << can_fit<long long, double>::value << std::endl;

    std::cout << can_fit<short, int>::value << std::endl;
    std::cout << can_fit<int, short>::value << std::endl;
}
// this is just stuff I use
#include <boost/type_traits/integral_constant.hpp>

template <bool B>
struct bool_type : boost::integral_constant<bool, B>
{
    static const bool value = B;
};

typedef const boost::true_type& true_tag;
typedef const boost::false_type& false_tag;

// can_fit type traits
#include <limits>

namespace detail
{
    template <typename T, typename U>
    struct can_fit
    {
        static const bool value = std::numeric_limits<T>::digits
                                <= std::numeric_limits<U>::digits;
    };
}

template <typename T, typename U>
struct can_fit : bool_type<detail::can_fit<T, U>::value>
{
    typedef T type1;
    typedef U type2;

    static const bool value = detail::can_fit<T, U>::value;
};

// test
#include <iostream>

namespace detail
{
    void foo(true_tag)
    {
        std::cout << "T fits in U" << std::endl;
    }

    void foo(false_tag)
    {
        std::cout << "T does not fit in U" << std::endl;
    }
}

// just an example
template <typename T, typename U>
void foo(void)
{
    detail::foo(can_fit<T, U>());
}

int main(void)
{
    foo<int, double>();
}