64位浮点数在所有现代PC上的表现都一样吗? [英] Does 64-bit floating point numbers behave identically on all modern PCs?

查看:62
本文介绍了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 = b c + d",其中所有变量都声明为double,则编译器可以自由使用双精度算术或使用范围或精度更高.例如,如果处理器具有能够保存扩展精度浮点数的寄存器,并且使用扩展精度进行算术不比使用双精度算术花费更多的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.

某些处理器具有一条指令来计算一个乘法和一个加法运算,因此"b c + d"的计算无需中间舍入,并且比在首先计算b 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(正确舍入的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天全站免登陆