Prevent "Float-point invalid operation" exception?

时间:2016-02-03 03:15:03

标签: c++ double

I am using Visual C++ to load binary data into float, like this:

  double dValue;
  memcpy(&dValue, lpData, sizeof(dValue));

For normal cases, this will work properly. However, for some rare cases, when binary data are corrupt, the dValue will be invalid and any further operations on it will cause “Float-point invalid operation” exception.

I check the dValue in debugger and it displays as -1.#QNAN00000000000.

To prevent the exception, I need to verify the dValue after it is loaded from the binary data. I try to use:

  if (_finite(dValue))
  {
   … do some tasks…
  }

But still the invalid dValue will cause _finite function to raise a Float-point invalid operation exception. Although _finite(dValue) will return 0 properly, the exception will be allocated in memory. Even if I deallocate it. Too many allocate/deallocate will still exhaust the system resources.

Therefore, is there a way to detect the validity of a double value without raising any exceptions?

1 个答案:

答案 0 :(得分:1)

我原本预计std::isnan会做你需要的,并且效率最高。如果您的平台上的实现不是这种情况,但您可以放心地假设浮点数使用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字节转换为浮点类型。