在C ++中编写符合IEEE-754标准的双/浮点分区的最快方法是什么?

时间:2017-06-23 09:23:13

标签: c++ division undefined-behavior ieee-754 divide-by-zero

我想在C ++中编写符合IEEE-754标准的部门,特别是关于零处理的除法:positive/0->Infnegative/0->-Infeverything else/0->NaN

虽然我机器上的一个简单的C ++分区 会导致这种行为,但C ++标准并没有强制要求这种语义。它是未定义的,所以我不能依赖它。

那么在C ++中实现它的最快方法是什么?当然,我可以这样做一个明确的测试:

double fdiv64(double numerator, double denominator)
{
   using limits=std::numeric_limits<double>;
   if (denominator==0.0) {
      if (numerator>0.0) {
         return limits::infinity();
      } else if (numerator<0.0) {
         return -limits::infinity();
      } else {
         return limits::quiet_NaN();
      }
   } else {
      return numerator/denominator;
   }
}

但是这引入了额外的分支,并且在我的机器上完全是多余的,因为无论如何我都能获得正确的行为。似乎没有符合IEEE-754标准的编译器内在函数。我可以使用内联汇编,但这也是非常不可移植的。

那么进行这种划分的最快方法是什么?

2 个答案:

答案 0 :(得分:4)

你不能这样做,我担心,除非你为不使用本机的平台在软件中构建自己的IEEE754浮点实现,即便如此,你的类型会有细微差别不是内置类型(例如&&||如果你超载则不会被短路);虽然用户定义的文字可能会有所帮助。

例如,infinity的支持是可选的,只有std::numeric_limits<T>::has_infinity == true适用于您的类型T才会在平台上展示。

因此,尝试优化您声称的可移植代码甚至不在桌面上。

参考文献:

http://en.cppreference.com/w/cpp/types/numeric_limits/infinity http://en.cppreference.com/w/cpp/language/user_literal

答案 1 :(得分:2)

你可能已经拥有了这一点,没有做任何特别的事情。在几种体系结构中,您可以指定CPU应该执行什么操作&#34; special&#34;情况(除以零等)。看看fesetenv。编译器通常有关于如何处理浮点数学的开关。例如,请查看Visual Studio的cl.exe option

如果你继续使用x86架构(并使用内部精度设置为float / double的SSE或x87,请参阅下面的链接了解详细信息),我认为您可以开箱即用IEEE754行为(因此您的程序可以正常工作)在任何x86机器上,而不仅仅是你的。)

如果您的CPU不能遵循IEEE754,那么您可能必须使用完整的软件浮点实现。或者也许你可以使用硬件,你只需要处理特殊情况。

但通常,今天,几乎所有东西(PC,移动设备)都使用IEEE754:

在SW实现中,您必须从浮点数中提取符号,指数,尾数,并自己进行数学运算。

注意:即使除数不为零,也可以使用小(低于正常)数字,也可以得到inf结果。这是因为最大。浮点数在~10 ^ 38范围内,但最小但正数在~10 ^ -45范围内。