精确龙格 - 库塔系数

问题描述 投票:1回答:2

当使用数值方法(例如Runge-Kutta)时,计算机上浮点数的有限精度会影响解(Brouwer定律)。

this paper中,它建议作为模拟精确Runge-Kutta系数的补救措施,例如A = B + C其中B是精确的机器编号,C是一些小的校正

谁能解释一下这在实践中是如何运作的?例如。如果A = 3/10,那么如何确定B和C?

谢谢你的帮助。

floating-point precision numerical-methods floating-accuracy
2个回答
2
投票

在论文中,他们建议对分母1024使用A的有理逼近。(这意味着A最多有10个有效的非零位)。你有(3/10)* 1024 = 307.2,所以B会

B = 307/1024 = 0.2998046875,C = A-B = 0.0001953125

C不能完全表示为IEEE Binary64,最近的浮点数将是

C = 1.9531249999998889776975374843 ... E-4。

在公式(3.1f)中插入这些值


1
投票

这个技巧可能在2007年提交论文时起作用,但我认为它不太可能在现代平台上运行。

在现代x86(32位和64位)处理器上,有两个独立的浮点计算指令集:

  • 较旧的x87指令(可以追溯到最初的8087协处理器),它有80位寄存器
  • 更新的SSE指令,它使用与格式相同宽度的寄存器(float为32位,double为64位)。

较新的SSE指令通常是现代编译器首选,因为它们可以更快,因为它们可以完全流水线化,并支持像SIMD操作这样的奇特事物。但是在2007年,一些编译器默认只使用x87指令,因为二进制文件可以在旧机器上使用(在32位机器上尤其如此)。

80位寄存器支持高达64位的有效位,比64位double的53位有效位数高11位。这个想法是你可以减少中间舍入错误,在这种情况下你可以利用。

考虑一个更简单的问题版本:计算

Y = A*X

通过将A分成B+C,他们建议,B只有10个有效位。然后操作

B*X

不会产生任何舍入误差,因为它最多会有63个有效位。完整的计算

Y = B*X + C*X

因此,您将获得几乎全部64位精度的结果。

如果没有扩展的精度,B*X通常会产生大致相同大小的舍入误差,就像你直接计算A*X一样(除非X本身已经以降低精度存储)。

现在这听起来很棒:你可能想知道为什么SSE指令摆脱了这个?不幸的是,它是不可预测的:在某些情况下,编译器会安排它以便这可以工作,但在其他情况下,它需要将寄存器“​​溢出”到内存中,在这种情况下,您将失去这种额外的精度。这反过来会产生奇怪的结果,例如将x+y == x+y等操作评估为false,具体取决于评估各个操作的时间。

但是,一切都不会丢失!如果你有一台相当新的机器,你可以利用fused multiply-add (fma)操作来提高准确性。在这种情况下,它看起来像

Y = fma(B,X,C*X)
© www.soinside.com 2019 - 2024. All rights reserved.