gpt4 book ai didi

c++ - 浮点/整数类型转换的可靠溢出检测

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:59:18 29 4
gpt4 key购买 nike

有没有安全的方法来可靠地确定整数类型 T可以存储浮点整数值 f (所以 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
}

有什么想法吗?

最佳答案

Is there a safe way to reliably determine if an integral type T can store a floating-point integer value f?

是的。关键是测试 f 是否在 T::MIN - 0.999...T::MAX + 0.999... 范围内> 使用 float 学 - 没有舍入问题。奖励:舍入模式不适用。

有 3 条失败路径:太大、太小、不是数字。


The below assumes int/double. I'll leave the C++ template forming for OP.

使用 float 学精确地形成精确的 T::MAX + 1 很容易,因为 INT_MAXMersenne Number . (我们在这里不是在谈论梅森素数。)

代码利用了:
梅森数除以 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))

形成精确的 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();
}
}

关于具有非二进制基数的浮点类型 (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 为基数。

关于c++ - 浮点/整数类型转换的可靠溢出检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51304323/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com