64 位浮点数在所有现代 PC 上的行为是否相同? [英] Does 64-bit floating point numbers behave identically on all modern PCs?

查看:26
本文介绍了64 位浮点数在所有现代 PC 上的行为是否相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道我是否可以假设对相同的 64 位浮点数进行相同的操作在任何现代 PC 和最常见的编程语言中给出完全相同的结果?(C++、Java、C# 等).我们可以假设,我们正在对数字进行运算,结果也是一个数字(没有 NaN、INF 等).

I would like to know whether i can assume that same operations on same 64-bit floating point numbers gives exactly the same results on any modern PC and in most common programming languages? (C++, Java, C#, etc.). We can assume, that we are operating on numbers and result is also a number (no NaNs, INFs and so on).

我知道有两个非常相似的使用浮点数的计算标准(IEEE 854-1987 和 IEEE 754-2008).但是我不知道实际情况如何.

I know there are two very simmilar standards of computation using floating point numbers (IEEE 854-1987 and IEEE 754-2008). However I don't know how it is in practice.

推荐答案

实现 64 位浮点的现代处理器通常实现与 IEEE 754-1985 标准(最近被 754-2008 标准取代)相近的东西.

Modern processors that implement 64-bit floating-point typically implement something that is close to the IEEE 754-1985 standard, recently superseded by the 754-2008 standard.

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

The 754 standard specifies what result you should get from certain basic operations, notably addition, subtraction, multiplication, division, square root, and negation. In most cases, the numeric result is specified precisely: The result must be the representable number that is closest to the exact mathematical result in the direction specified by the rounding mode (to nearest, toward infinity, toward zero, or toward negative infinity). In "to nearest" mode, the standard also specifies how ties are broken.

正因如此,不涉及溢出等异常条件的操作,在符合标准的不同处理器上会得到相同的结果.

Because of this, operations that do not involve exception conditions such as overflow will get the same results on different processors that conform to the standard.

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

However, there are several issues that interfere with getting identical results on different processors. One of them is that the compiler is often free to implement sequences of floating-point operations in a variety of ways. For example, if you write "a = bc + d" in C, where all variables are declared double, the compiler is free to compute "bc" in either double-precision arithmetic or something with more range or precision. If, for example, the processor has registers capable of holding extended-precision floating-point numbers and doing arithmetic with extended-precision does not take any more CPU time than doing arithmetic with double-precision, a compiler is likely to generate code using extended-precision. On such a processor, you might not get the same results as you would on another processor. Even if the compiler does this regularly, it might not in some circumstances because the registers are full during a complicated sequence, so it stores the intermediate results in memory temporarily. When it does that, it might write just the 64-bit double rather than the extended-precision number. So a routine containing floating-point arithmetic might give different results just because it was compiled with different code, perhaps inlined in one place, and the compiler needed registers for something else.

某些处理器具有在一条指令中计算乘法和加法的指令,因此bc + d"可以在没有中间舍入的情况下进行计算,并且比在首先计算 b<的处理器上获得更准确的结果/em>c 然后加上 d.

Some processors have instructions to compute a multiply and an add in one instruction, so "bc + d" might be computed with no intermediate rounding and get a more accurate result than on a processor that first computes bc and then adds d.

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

Your compiler might have switches to control behavior like this.

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

There are some places where the 754-1985 standard does not require a unique result. For example, when determining whether underflow has occurred (a result is too small to be represented accurately), the standard allows an implementation to make the determination either before or after it rounds the significand (the fraction bits) to the target precision. So some implementations will tell you underflow has occurred when other implementations will not.

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

A common feature in processors is to have an "almost IEEE 754" mode that eliminates the difficulty of dealing with underflow by substituting zero instead of returning the very small number that the standard requires. Naturally, you will get different numbers when executing in such a mode than when executing in the more compliant mode. The non-compliant mode may be the default set by your compiler and/or operating system, for reasons of performance.

请注意,IEEE 754 实现通常不仅仅由硬件提供,而是由硬件和软件的组合提供.处理器可能会完成大部分工作,但依赖软件来处理某些异常、设置某些模式等.

Note that an IEEE 754 implementation is typically not provided just by hardware but by a combination of hardware and software. The processor may do the bulk of the work but rely on the software to handle certain exceptions, set certain modes, and so on.

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

When you move beyond the basic arithmetic operations to things like sine and cosine, you are very dependent on the library you use. Transcendental functions are generally calculated with carefully engineered approximations. The implementations are developed independently by various engineers and get different results from each other. On one system, the sin function may give results accurate within an ULP (unit of least precision) for small arguments (less than pi or so) but larger errors for large arguments. On another system, the sin function might give results accurate within several ULP for all arguments. No current math library is known to produce correctly rounded results for all inputs. There is a project, crlibm (Correctly Rounded Libm), that has done some good work toward this goal, and they have developed implementations for significant parts of the math library that are correctly rounded and have good performance, but not all of the math library yet.

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

In summary, if you have a manageable set of calculations, understand your compiler implementation, and are very careful, you can rely on identical results on different processors. Otherwise, getting completely identical results is not something you can rely on.

这篇关于64 位浮点数在所有现代 PC 上的行为是否相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆