假设使用C中的IEEE754浮点表示浮点数是否安全?

时间:2015-08-12 13:44:16

标签: c floating-point ieee-754

浮点是C中定义的实现。所以没有任何保证。

我们的代码需要是可移植的,我们正在讨论在我们的协议中使用IEEE754浮点数是否可以接受。出于性能原因,如果我们不必在发送或接收数据时在固定点格式之间来回转换,那将是很好的。

虽然我知道平台和架构之间可能存在关于longwchar_t大小的差异。但我似乎无法找到有关floatdouble的具体信息。

到目前为止,我发现字节顺序可能在大端平台上反转。虽然有些平台没有浮点支持,但包含floatdouble的代码甚至无法链接。否则平台似乎坚持IEEE754单精度和双精度。

因此可以假设浮点数在IEEE754可用时是安全的吗?

编辑:回应评论:

  

您对“安全”的定义是什么?

安全我的意思是,一个系统上的位模式在另一个系统上意味着相同(在字节旋转之后处理字节序)。

6 个答案:

答案 0 :(得分:25)

基本上所有当前非穿卡使用的架构,包括嵌入式架构和外来信号处理架构,都提供了两个浮点系统之一:

  • IEEE-754。
  • IEEE-754 除了blah 。也就是说,他们主要是实现754,但在一些更昂贵和/或繁琐的位上便宜。

最常见的便宜货:

  • 将非正规值刷新为零。这使某些有时有用的定理无效(特别是,如果a-ba在2的因子内,b可以精确表示的定理),但在实践中它是'通常不会成为一个问题。
  • 未能将infNaN视为特殊内容。这些体系结构将无法遵循有关infNaN作为操作数的规则,并且可能无法满足inf,而是生成大于FLT_MAX的数字,这通常会被其他架构认可为NaN
  • 正确舍入除法和平方根。确保结果在精确结果的1-3 ulps内比在1/2 ulp内更容易保证。一个特别常见的情况是将除法实现为倒数+乘法,这会使你失去一点精度。
  • 更少或没有保护数字。这是一个不寻常的廉价,但意味着其他操作可以1-2卢比。

BUUUUT ......即使那些除了blah 架构仍然使用IEEE-754的数字表示。除了字节排序问题之外,架构A上描述floatdouble的位基本上保证在架构B上具有相同的含义。

因此,只要你关心的只是价值观的代表,你就完全没问题了。如果您关心跨平台操作的一致性,您可能需要做一些额外的工作。

编辑:正如Chux在评论中提到的,平台之间常见的额外不一致来源是使用扩展精度,例如x87的80位内部表示。这与廉价的相反,并且(通过适当的处理)完全符合IEEE-754和C标准,但它同样会导致架构之间的结果不同,甚至在编译器版本和显然之间次要和不相关的代码更改。但是:由于扩展的精度,特定的x86 / x64可执行文件不会在不同的处理器上产生不同的结果。

答案 1 :(得分:7)

有一个要检查的宏(自C99起):

  

C11§6.10.8.3条件特征宏

     

__STDC_IEC_559__整数常量1,用于表示符合附录F(IEC 60559浮点运算)中的规范。

IEC 60559 ISO / IEC / IEEE 60559 的缩写)是IEEE-754的另一个名称。

附件F然后建立C浮动类型和IEEE-754类型之间的映射:

  

C浮点类型符合IEC 60559格式,如下所示:

     
      
  • 浮点类型符合IEC 60559单一格式。
  •   
  • 双重类型符合IEC 60559双重格式。
  •   
  • long double类型符合IEC 60559扩展格式,357)否则a   非IEC 60559扩展格式,否则为IEC 60559双格式。
  •   

答案 2 :(得分:3)

我建议您需要仔细查看便携式的定义。

我还建议您定义" safe"不够。即使二进制表示(允许字节顺序)没问题,对变量的操作也可能表现不同。毕竟,浮点数的应用很少,不涉及对变量的操作。

如果您想支持所有已创建的主机架构,那么假设IEEE浮点格式本质上是不安全的。您将不得不处理支持不同格式的系统,根本不支持浮点的系统,编译器有交换机选择浮点行为的系统(某些行为与非IEEE格式相关联),CPU有一个可选的协处理器(因此浮点支持取决于是否安装了额外的芯片,但CPU的其他变体是相同的),在软件中模拟浮点运算的系统(某些此类软件仿真器可在运行时配置) ,以及浮点(可能是也可能不是基于IEEE)的错误或不完整实现的系统。

如果您愿意将自己限制在2000年以后的硬件上,那么您的风险会降低但不会为零。实际上,该年份的所有CPU都以某种形式支持IEEE。但是,您仍然(与旧CPU一样)需要考虑您希望支持的浮点运算,以及您愿意接受的权衡取舍。不同的CPU(或软件仿真)具有比其他CPU更不完整的浮点实现,并且一些默认配置为不支持某些功能 - 因此有必要更改设置以启用某些功能,这些功能可能会影响您的性能或正确性代码。

如果您需要在应用程序之间共享浮点值(可能在具有不同功能的不同主机上,使用不同的编译器构建等),那么您将需要定义协议。该协议可能涉及IEEE格式,但您的所有应用程序都需要能够处理协议与其本机表示之间的转换。

答案 3 :(得分:2)

几乎所有常见架构现在都使用IEEE-754,标准不要求这样做。曾经有旧的非IEE-754架构,有些可能仍然存在。

如果唯一的要求是交换网络数据,我的建议是:

  • 如果定义了__STDC_IEC_559__,则仅对字节使用网络顺序,并假设您有浮标和双倍的标准IEE-754。
  • 如果未定义__STDC_IEC_559__,请使用特殊的交换格式,可能是IEE-754 - 一个协议 - 或其他任何 - 需要协议指示。

答案 4 :(得分:1)

严格地说,假设浮点支持是不安全的;一般来说,绝大多数平台都会支持它。值得注意的例外包括(现已弃用)在Alpha芯片上运行的VMS系统

如果您有足够的运行时检查,请考虑paranoiaWilliam Kahan编写的浮点审查工具。

编辑:听起来您的应用程序更关注二进制格式,因为它们与存储和/或序列化有关。我建议缩小范围,选择支持此功能的第三方库。你可能会比Google Protocol Buffers更糟糕。

答案 5 :(得分:1)

就像其他人提到的那样,有success: function (data) { $("#target embed").attr("src", "handlers/loadPDFHandler.ashx?fileName=Bid" + record + ".pdf"); // alert(data); // $("#target embed").body.update(display.data); 宏,但它并不是非常有用,因为它只能由完全实现C标准中相应附件的编译器设置。有些编译器只实现了一个子集,但仍然(大部分)可以使用IEEE浮点支持。

如果您只关注二进制表示,则应编写功能测试,以检查某些浮点数的位模式。类似的东西:

__STDC_IEC_559__

使用不同的指数,尾数和符号检查几个数字,您应该保证安全。由于这些测试并不昂贵,您甚至可以在运行时运行它们一次。