如何为浮点类型RealType匹配可被其完整存储的无符号整型SizeType
解决方法
要找到能被给定浮点类型RealType精确存储所有取值的最大无符号整型SizeType,核心思路是利用浮点数的精确整数表示范围——二进制浮点数只能精确表示位数不超过其尾数有效位(含隐含位)的整数。我们可以通过编译期模板实现类型推导,步骤如下:
1. 判断无符号类型是否满足条件
先定义类型特征,检查某个无符号类型的所有值是否能被目标浮点类型精确存储:
#include <type_traits> #include <limits> template <typename Real> struct max_precise_uint_bits : std::integral_constant< int, std::numeric_limits<Real>::digits + 1 > {}; template <typename Real, typename UInt> struct can_hold_all_uint : std::bool_constant< std::numeric_limits<UInt>::digits <= max_precise_uint_bits<Real>::value > {};
max_precise_uint_bits<Real>:计算浮点类型能精确表示的最大整数的二进制位数(尾数显式位+隐含的1位)。can_hold_all_uint<Real, UInt>:判断无符号类型UInt的二进制位数是否不超过上述上限,若是则所有UInt值都能被Real精确存储。
2. 从候选类型中选出最大符合条件的类型
通过递归模板从常用无符号类型中筛选出最大的符合条件的类型:
// 递归终止:仅剩一个候选类型时直接返回 template <typename Real, typename UInt> struct largest_uint_holdable { using type = UInt; }; // 递归比较:依次检查候选类型,保留最大的符合条件的类型 template <typename Real, typename UInt1, typename UInt2, typename... Rest> struct largest_uint_holdable<Real, UInt1, UInt2, Rest...> { private: using next_candidate = typename largest_uint_holdable<Real, UInt2, Rest...>::type; public: using type = std::conditional_t< can_hold_all_uint<Real, UInt1>::value && (sizeof(UInt1) >= sizeof(next_candidate)), UInt1, next_candidate >; }; // 别名模板,简化使用 template <typename Real> using largest_uint_holdable_t = typename largest_uint_holdable< Real, std::uint8_t, std::uint16_t, std::uint32_t, std::uint64_t #ifdef __SIZEOF_INT128__ , __uint128_t #endif >::type;
3. 测试示例
#include <cstdint> int main() { // float能精确存储的最大标准无符号类型是uint16_t(uint32_t位数超过float的精确范围) static_assert(std::is_same_v<largest_uint_holdable_t<float>, std::uint16_t>); // double能精确存储的最大标准无符号类型是uint32_t(uint64_t位数超过double的精确范围) static_assert(std::is_same_v<largest_uint_holdable_t<double>, std::uint32_t>); // x86平台的long double(80位)能精确存储uint64_t static_assert(std::is_same_v<largest_uint_holdable_t<long double>, std::uint64_t>); }
说明
- 对于非IEEE 754的浮点实现,
std::numeric_limits<Real>::digits仍能正确反映尾数的有效二进制位数,方案具备通用性。 - 若编译器支持
__uint128_t,代码会自动将其加入候选列表,但只有当浮点类型的精确范围覆盖128位整数时才会选中它。
内容的提问来源于stack exchange,提问作者0xbadf00d
相关产品推荐
相关产品推荐

