首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >64位浮点数在所有现代PC上的行为都是一样的吗?

64位浮点数在所有现代PC上的行为都是一样的吗?
EN

Stack Overflow用户
提问于 2010-01-28 04:07:23
回答 7查看 902关注 0票数 10

我想知道,我是否可以假设对相同的64位浮点数进行相同的操作,在任何现代PC和大多数常用编程语言中都会产生完全相同的结果?(C++、Java、C#等)。我们可以假设,我们正在对数字进行操作,结果也是一个数字(没有NaNs、INFs等)。

我知道使用浮点数的计算有两个非常相似的标准(IEEE854-1987和IEEE754-2008)。然而,我不知道它在实践中是如何实现的。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-01-28 05:26:26

实现64位浮点的现代处理器通常实现接近IEEE754-1985标准的内容,该标准最近被754-2008标准所取代。

754标准规定了从某些基本运算中得到的结果,特别是加法、减法、乘法、除法、平方根和求反。在大多数情况下,数值结果都是精确指定的:结果必须是在舍入模式指定的方向上最接近精确数学结果的可表示数字(到最近、朝无穷大、朝零或朝负无穷大)。在“到最近的”模式中,该标准还指定了如何打破平局。

因此,不涉及溢出等异常条件的操作将在符合标准的不同处理器上获得相同的结果。

但是,有几个问题会影响在不同处理器上获得相同的结果。其中之一是编译器通常可以自由地以各种方式实现浮点操作序列。例如,如果您在C中编写"a = b_c + d“,其中所有变量都被声明为double,编译器可以自由地以双精度算术或更大范围或更高精度的算术来计算"b_c”。例如,如果处理器具有能够保存扩展精度浮点数的寄存器,并且使用扩展精度进行运算并不比使用双精度运算花费更多的CPU时间,则编译器很可能使用扩展精度生成代码。在这样的处理器上,您可能不会获得与在另一个处理器上相同的结果。即使编译器定期这样做,在某些情况下也可能不会,因为在复杂的序列期间寄存器是满的,所以它将中间结果临时存储在内存中。当它这样做时,它可能只写入64位的双精度数,而不是扩展精度的数字。因此,包含浮点运算的例程可能会给出不同的结果,因为它是用不同的代码编译的,可能是内联在一个地方,而编译器需要寄存器来做其他事情。

一些处理器在一条指令中包含计算乘法和加法的指令,因此可以在没有中间舍入的情况下计算"b_c + d“,并获得比先计算b_c然后计算d的处理器更精确的结果。

你的编译器可能有开关来控制这样的行为。

在某些地方,754-1985标准不需要唯一的结果。例如,当确定是否发生下溢(结果太小而无法准确表示)时,该标准允许实现在将有效数(分数位)舍入到目标精度之前或之后进行确定。因此,一些实现会告诉您发生了下溢,而其他实现则不会。

处理器中的一个共同特征是具有“几乎IEEE754”模式,该模式通过替换零而不是返回标准要求的非常小的数字来消除处理下溢的困难。当然,在这种模式下执行时会得到与在更兼容模式下执行时不同的数字。出于性能原因,非兼容模式可能是您的编译器和/或操作系统设置的默认模式。

注意,IEEE754实现通常不仅由硬件提供,而且由硬件和软件的组合提供。处理器可以完成大部分工作,但依赖于软件来处理某些异常、设置某些模式等。

当你从基本的算术运算转移到像正弦和余弦这样的东西时,你非常依赖于你所使用的库。超越函数通常是通过精心设计的近似计算的。这些实现是由不同的工程师独立开发的,并得到了不同的结果。在一个系统上,对于较小的参数(小于pi左右),sin函数可以在ULP (最小精度单位)内给出准确的结果,但对于较大的参数,可以给出较大的误差。在另一个系统上,对于所有参数,sin函数可能会在几个ULP内给出准确的结果。目前还没有已知的数学库可以为所有输入生成正确的舍入结果。有一个项目,crlibm (正确舍入的Libm),已经为这个目标做了一些很好的工作,他们已经为数学库的重要部分开发了实现,这些部分经过了正确的舍入并具有良好的性能,但还不是所有的数学库。

总而言之,如果您有一组可管理的计算,了解您的编译器实现,并且非常小心,那么您可以在不同的处理器上依赖相同的结果。否则,得到完全相同的结果就不是你可以依赖的了。

票数 8
EN

Stack Overflow用户

发布于 2010-01-28 04:28:26

如果你的意思是得到完全相同的结果,那么答案是否定的。

在某些情况下,您甚至可能在同一台机器上调试(非优化)构建与发布构建(优化)得到不同的结果,所以甚至不要假设在不同的机器上结果可能总是相同的。

(例如,在采用Intel处理器的计算机上,如果优化器将中间结果的变量保存在寄存器中,该变量存储在未优化构建的内存中,则可能会发生这种情况。由于Intel FPU寄存器为80位,双精度变量为64位,因此中间结果在优化后的构建中将以更高的精度存储,从而在以后的结果中导致不同的值。)

然而,在实践中,您可能经常得到相同的结果,但您不应该依赖它。

票数 7
EN

Stack Overflow用户

发布于 2010-01-28 04:12:30

现代FPU都实现了单格式和双格式的IEEE754浮点,还有一些是扩展格式的浮点。它支持一组特定的操作(math.h中几乎所有的操作),并有一些特殊的指令。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2149900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档