0

我正在使用 Matlablinspace函数和范围:运算符来获得等距的向量,但我意外地收到了不等距的数字。我的代码如下:

format long

x1 = linspace(3,5,20);
diff(x1)

x2 = 3:0.1:5;
diff(x2)

向量差 ( diff) 的输出如下:

x1    
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737
0.105263157894737
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894736   
0.105263157894737   
0.105263157894737   
0.105263157894736
0.105263157894737   
0.105263157894736   
0.105263157894737

x2
0.100000000000000   
0.100000000000000   
0.100000000000000   
0.100000000000000
0.100000000000000   
0.100000000000000   
0.100000000000000   
0.100000000000000
0.100000000000000   
0.100000000000000   
0.100000000000000   
0.100000000000001
0.100000000000000   
0.100000000000001   
0.100000000000000   
0.100000000000000
0.100000000000001   
0.100000000000000   
0.100000000000001   
0.100000000000000

为了解决这个问题,我通过以下代码使用 Kahan 求和方法:

dx = 2/19;
x3 = zeros(size(x1));
x3(1) = 0;
partial_sum = 0;
c = 0.0;
for k=2:20,
    y = dx - c;
    t = partial_sum + y;
    c = (t - partial_sum) - y;
    partial_sum = t;
    x3(k) = partial_sum;
end
diff(x3)

我现在正在获得一个等距向量

0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737   
0.105263157894737
0.105263157894737   
0.105263157894737   
0.105263157894737

但是,这种方法是“顺序的”。是否有人知道 Kahan 求和方法的矢量化或并行实现以提高效率或将其移植到(CUDA)并行减少?

先感谢您。

4

2 回答 2

4

我认为你是误会了

(a)的使用linspace。你的来电

linspace(3,5,20)

返回 20 个等距数字,从 3 开始,到 5 结束。试试

linspace(3,5,21)

反而。请注意,向量的长度xx2相差一。

( b)

浮点运算的微妙之处。这个主题在 SO 上得到了广泛的介绍,我不会复制已经找到的许多好的解释中的任何一个。

我认为您所看到的是对于大多数数值应用来说等距的数字

于 2013-04-19T09:03:32.820 回答
3

我想这个链接会有所帮助:

http://www.mathworks.com/matlabcentral/fileexchange/26800

您将找到该XSum功能,您可以在其中切换和测试不同的求和方法:

  • Double:Matlab 的 SUM 的线程安全实现。至少在 Matlab 2008a 到 2009b 中,多线程 SUM 的结果可能因调用而异。比单线程 SUM (MSVC++ 2008) 快 50%,精度相当。
  • Long:如果编译器支持(例如 LCC v3.8),则以 80 位 long double 形式累积。多 3.5 个有效数字,慢 40%。
  • Kahan:从下一个元素中减去局部误差。多 1 到 3 个有效数字,慢 10%。
  • Knuth:好像总和是在一个 128 位浮点数中累积的:大约还有 15 个有效数字。大约相同的速度(MSVC++2008 编译器)。这适用于最现实的问题。
  • Knuth2:30 个有效数字,就好像它以 196 位浮点数累加一样。慢 60%。
  • KnuthLong:与 Knuth 相同,但如果编译器支持,则使用 long double 来获得大约 21 个有效数字。慢 2.5 倍。
于 2013-04-19T09:07:26.243 回答