c++ - 编译时可以平方而不溢出的最大值是多少(整数类型)?
问题描述
在 C++ 中,是否有一种编译时方法来计算可以安全平方的整数类型的最大值T
,即在数学x * x <= std::numeric_limits<T>::max()
上,如果x*x
要执行操作,它不会导致未定义的行为(对于有符号类型)或溢出(对于无符号类型?
我很好地限制了只有在std::numeric_limits
.
数学上,答案当然是floor(sqrt(std::numeric_limits<T>::max()))
。例如,这将是floor(sqrt(2^63-1)) == 3037000499
一个 64 位有符号的 long long。A(即使对于大数也是正确的) constexpr sqrt 可以解决问题,尽管我不知道这是否是最好的方法。
答案应该是:
- 64 位无符号:
floor(sqrt(2^64-1)) == 4294967295
- 64 位签名:
floor(sqrt(2^63-1)) == 3037000499
- 32 位无符号:
floor(sqrt(2^32-1)) == 65535
- 32 位签名:
floor(sqrt(2^31-1)) == 46340
解决方案
- 设置位的下半部分。
- 对于有符号类型,加 1 然后除以
sqrt(2)
#include <climits>
#include <limits>
#include <type_traits>
template<class T>
constexpr T largest_squareable() {
static_assert(std::is_integral_v<T>, "Must be an integral type");
if constexpr (std::is_unsigned_v<T>) {
return std::numeric_limits<T>::max() >> sizeof(T) * CHAR_BIT / 2;
} else {
constexpr long double sqrt_2 = 1.41421356237309504880L;
return (largest_squareable<std::make_unsigned_t<T>>() + 1) / sqrt_2;
}
}
或者只是手动定义值,因为大小的数量非常有限:
#include <cstdint>
template<typename T>
constexpr T largest_squareable();
template<> constexpr int8_t largest_squareable<int8_t>() { return 11; }
template<> constexpr uint8_t largest_squareable<uint8_t>() { return 15; }
template<> constexpr int16_t largest_squareable<int16_t>() { return 181; }
template<> constexpr uint16_t largest_squareable<uint16_t>() { return 255; }
template<> constexpr int32_t largest_squareable<int32_t>() { return 46340L; }
template<> constexpr uint32_t largest_squareable<uint32_t>() { return 65535UL; }
template<> constexpr int64_t largest_squareable<int64_t>() { return 3037000499LL; }
template<> constexpr uint64_t largest_squareable<uint64_t>() { return 4294967295ULL; }
推荐阅读
- json - Flutter:如何映射字典?通过字典制作下拉选项
- json - 使用 Moshi 处理可能是列表或自定义对象的 JSON 响应
- javascript - 点击时如何从表单中获取数据?
- amazon-web-services - api 网关与 aws 批处理集成
- visual-studio - 签入策略 Visual Studio - 如果在定义的模板中,则检查变更集注释
- java - 启动 Tomcat 时 JavaMelody 抛出 NullPointerException
- python - 如何更改连接器形状连接到其他形状时的外观?
- angular - 在与 TemplateRef 相同的组件中访问 Angular ng-template
- java - 与面向对象的方法作斗争
- java - Spring注解方法用途