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;
}
这打印:
2147483647
2147483647.000000
9223372036854775807
9223372036854775800.000000
2147483647
2147483648.000000
注意最大int
可以装入一个double
不损失精度和boost::intmax_t
(在本例中为 64 位)不能。float
甚至不能持有int
.
现在,问题是:C++ 中有没有一种方法可以检查给定整数类型的整个范围是否可以适合浮点类型而不损失精度?
优选地,
- 这将是一个可以在静态断言中使用的编译时检查,
- 并且不会涉及枚举编译器应该知道或可以计算的常量。
只是一个小谓词:
#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;
}
测试二进制精度是否可用T
存在于一个U
。适用于所有类型。
“增强”:
// 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>();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)