pla*_*cel 5 c++ floating-point integer integer-overflow type-conversion
有没有一种安全的方法来可靠地确定整数类型是否T可以存储浮点整数值f( so f == floor(f))而不会发生任何溢出?
请记住,不能保证浮点类型F与 IEC 559 (IEEE 754) 兼容,并且有符号整数溢出是C++ 中的未定义行为。我对根据当前 C++(编写时为 C++17)标准正确并避免未定义行为的解决方案感兴趣。
以下幼稚的方法不可靠,因为由于浮点舍入,不能保证类型F可以表示std::numeric_limits<I>::max()。
#include <cmath>
#include <limits>
#include <type_traits>
template <typename I, typename F>
bool is_safe_conversion(F x)
{
static_assert(std::is_floating_point_v<F>);
static_assert(std::is_integral_v<I>);
// 'fmax' may have a different value than expected
static constexpr F fmax = static_cast<F>(std::numeric_limits<I>::max());
return std::abs(x) <= fmax; // this test may gives incorrect results
}
Run Code Online (Sandbox Code Playgroud)
任何的想法?
有没有一种安全的方法来可靠地确定整数类型 T 是否可以存储浮点整数值 f?
是的。关键是测试是否在使用浮点数学的f范围内- 没有舍入问题。奖励:舍入模式不适用。T::MIN - 0.999...T::MAX + 0.999...
有 3 种失败路径:太大、太小、不是数字。
以下假设
int/double. 我将把 C++ 模板的形成留给 OP。
T::MAX + 1 使用浮点数学精确地形成精确值就像梅森数INT_MAX一样容易。(我们这里讨论的不是Mersenne Prime。)
代码利用了:用整数
数学除以 2 的梅森数也是梅森数。
整数类型的 2 次幂常量到浮点类型的转换可以肯定是精确的。
#define DBL_INT_MAXP1 (2.0*(INT_MAX/2+1))
// Below needed when -INT_MAX == INT_MIN
#define DBL_INT_MINM1 (2.0*(INT_MIN/2-1))
Run Code Online (Sandbox Code Playgroud)
形成精确值T::MIN - 1是很困难的,因为它的绝对值通常是 2 + 1 的幂,并且整数类型和 FP 类型的相对精度不确定。相反,代码可以减去 2 的精确幂并与 -1 进行比较。
int double_to_int(double x) {
if (x < DBL_INT_MAXP1) {
#if -INT_MAX == INT_MIN
// rare non-2's complement machine
if (x > DBL_INT_MINM1) {
return (int) x;
}
#else
if (x - INT_MIN > -1.0) {
return (int) x;
}
#endif
Handle_Underflow();
} else if (x > 0) {
Handle_Overflow();
} else {
Handle_NaN();
}
}
Run Code Online (Sandbox Code Playgroud)
FLT_RADIX != 2关于具有非二进制基数 ( )的浮点类型
使用FLT_RADIX = 4, 8, 16 ...,转换也将是准确的。使用 时FLT_RADIX == 10,代码至少精确到 34 位int,因为double必须精确编码 +/-10^10。FLT_RADIX == 10因此,64 位机器的问题int- 风险较低。根据记忆,最后一次FLT_RADIX == 10投产已经是十多年前了。
整数类型始终编码为 2 的补码(最常见)、1 的补码或符号大小。INT_MAX始终是 2 次幂减 1。INT_MIN总是 2 或 1 的 - 次幂。实际上,始终以 2 为底。
| 归档时间: |
|
| 查看次数: |
308 次 |
| 最近记录: |