我正在使用 Visual C++ 将二进制数据加载到 float
中,如下所示:
double dValue;
memcpy(&dValue, lpData, sizeof(dValue));
对于正常情况,这将正常工作。然而,在极少数情况下,当二进制数据损坏时,dValue
将无效,对其进行任何进一步操作将导致“浮点无效操作”异常。
我在调试器中检查了 dValue
,它显示为 -1.#QNAN00000000000
。
为了防止异常,我需要在从二进制数据加载后验证 dValue
。我尝试使用:
if (_finite(dValue))
{
… do some tasks…
}
但是无效的dValue
仍然会导致_finite
函数引发Float-point invalid operation
异常。虽然 _finite(dValue)
会正确返回 0,但异常会在内存中分配。即使我取消分配它。太多的分配/释放仍然会耗尽系统资源。
因此,有没有办法在不引发任何异常的情况下检测 double 值的有效性?
最佳答案
我本以为std::isnan
会做你需要做的并且最有效地做。如果您在平台上的实现不是这种情况,但假设 float 使用 IEEE 754 格式您觉得很舒服,那么您自己编写这些函数并不难。
inline constexpr bool
isnan(const std::uint32_t bits) noexcept
{
constexpr std::uint32_t exponent = UINT32_C(0x7f800000);
constexpr std::uint32_t mantissa = UINT32_C(0x007fffff);
return ((bits & exponent) == exponent) && ((bits & mantissa) != 0);
}
inline constexpr bool
isnan(const std::uint64_t bits) noexcept
{
constexpr std::uint64_t exponent = UINT64_C(0x7ff0000000000000);
constexpr std::uint64_t mantissa = UINT64_C(0x000fffffffffffff);
return ((bits & exponent) == exponent) && ((bits & mantissa) != 0);
}
实现 isfinite
更简单,您只需检查 (bits & exponent) != exponent
。要实现 isnormal
,请检查 ((bits & exponent) != exponent) && ((bits & exponent) != 0))
。请注意,根据此定义,零不是“正常”。
请注意,函数对整数类型进行操作。这是故意的。您的代码会将字节fread
转换为整数,您将整数传递给函数以确定它是否代表“非数字”,并且(仅)如果不是,则memcpy
将字节转换为浮点类型。
关于c++ - 防止 "Float-point invalid operation"异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35167866/