浮点运算和再现性

Gab*_*rdi 9 floating-point r ieee-754

IEEE-754算法在不同平台上是否可重现?

我正在测试一些用R编写的代码,它使用随机数.我认为在所有测试平台上设置随机数生成器的种子会使测试可重现,但这似乎不适用于rexp()生成指数分布的随机数.

这是我在32位Linux上得到的:

options(digits=22) ; set.seed(9) ; rexp(1, 5)
# [1] 0.2806184054728815824298
sessionInfo()
# R version 3.0.2 (2013-09-25)
# Platform: i686-pc-linux-gnu (32-bit)
Run Code Online (Sandbox Code Playgroud)

这就是我在64位OSX 10.9上得到的:

options(digits=22) ; set.seed(9) ; rexp(1, 5)
# [1] 0.2806184054728815269186
sessionInfo()
# R version 3.0.2 (2013-09-25)
# Platform: x86_64-apple-darwin10.8.0 (64-bit)
Run Code Online (Sandbox Code Playgroud)

64位Linux提供与64位OSX相同的结果,因此这似乎是32位与64位问题.

让我们假设两个R版本都使用相同的GCC版本编译,并使用相同的(默认R)编译标志,使编译器使用IEEE-754算法.

我的问题是,这可以被视为R中的一个错误吗?或者它只是使用近似有限精度浮点运算的"正常"结果?

我把相同的问题发送到R-devel邮件列表,但是没有在列表中找到答案,只有一个答案是私下的,试图说服我这不是一个错误,我应该忍受它.

这就是IEEE-754关于再现性的说法(来自维基百科):

IEEE 754-1985允许实现中的许多变化(例如某些值的编码和某些异常的检测).IEEE 754-2008已经收紧了其中许多,但仍然存在一些变化(特别是对于二进制格式).可再现性条款建议语言标准应提供编写可重现程序的方法(即,在语言的所有实现中产生相同结果的程序),并描述需要采取哪些措施才能获得可重现的结果.

这是在"建议"下.

我(主观)意见认为这是一个错误,因为IEEE-754标准的重点是具有可重现的,与平台无关的浮点运算.

Eri*_*hil 19

在高级语言中甚至可以重现基本浮点运算的问题,但它们通常可以通过各种特定于平台的操作来控制,例如设置编译器开关,使用自定义代码设置浮点控制和模式,或者,如果必要的,在装配中编写基本操作.正如在注释中开发的那样,您遇到的具体问题可能是不同的C实现使用不同的精度来评估中间浮点表达式.通常,这可以通过编译器开关控制,或者通过在表达式中包括转换和赋值来要求舍入到标称类型(从而丢弃过多的精度).

然而,更复杂的功能,例如expcos,在不同平台上不能例行地再现.尽管2008 IEEE-754标准建议使用正确的舍入来实现这些功能,但是对于任何已知有限运行时间的数学库,此任务尚未完成.世界上没有人做过数学来完成这个任务.

CRlibm项目已经实施了一些与已知的运行时间界限的功能,但工作是不完整的.(Per Pascal Cuoq的评论,当CRlibm没有经过验证的正确舍入运行时限时,由于计算精度非常高,它很可能会被正确舍入.)找出如何正确传递接地导致有限的时间并且证明它对于许多功能来说是困难的.(考虑如何证明没有价值cos(x),这里x是任何double值,比一些小的距离更近e,从两个可表示值之间的中点.中点是重要的,因为它就是四舍五入必须从一个结果返回到返回另一个改变,e告诉您如何准确和精确地计算近似值以提供正确的舍入.)

当前的事态是数学库中的许多函数是近似的,一些准确性比正确的舍入更加松散,并且不同的供应商使用具有不同近似的不同实现.我假设R在其rexp实现中使用了一些这些函数,并且它使用其目标平台的本机库,因此它在不同平台上获得不同的结果.

要解决此问题,您可以考虑在目标平台上使用通用数学库(可能是CRlibm).

  • 从技术上讲,CRlibm提供了有限的执行时间和已知的运行时限:它只能将计算推高到512位精度,用于非精确的函数情况,最坏的情况是未知的.这意味着对于某些功能,它没有被正确地舍入,而是"正确地舍入天文信心".替代方案在http://lipforge.ens-lyon.fr/frs/download.php/153/crlibm-1.0beta3.pdf的1.3.5节中讨论. (2认同)