c++ - 防止 "Float-point invalid operation"异常?

标签 c++ double

我正在使用 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/

相关文章:

.net - 是否有用于组合框的内置 .net string/double 对象?

java.lang.NumberFormatException : Invalid double: "١2" Problem with numbers processing in Persian

java - 在java中将 double 转换为二进制数

c++ - 具有嵌套类的模板类

c++ - 实现链表 : head insertion and destructor

c++ - 数组的 auto_ptr、unique_ptr 和 shared_ptr 的设计行为

c++ - 在 64 位处理器上不使用 double(而是使用 float)有什么好处吗?

c++ - 如何在派生类上强制派生类成员

c++ - 将整数输入数组的方法比 scanf() 或 cin 更快?

c - 使用 rand() 在 C 中填充矩阵