返回值因矢量大小而异

时间:2016-07-22 15:35:46

标签: matlab

我注意到例如log(x)函数在MATLAB中使用不同大小的向量调用时返回稍微不同的值。

这是一个最小的工作示例:

x1 = 0.1:0.1:1;
x2 = 0.1:0.1:1.1;

y1 = log(x1);
y2 = log(x2);

d = y1 - y2(1:length(x1));

d(7)

执行退货:

>> ans = 
  -1.6653e-16

当向量变得大于10个条目时,行为似乎就开始了。

虽然差异非常小,但是当使用大型向量进行大量操作缩放时,错误变得非常大,值得注意。

有没有人知道这里发生了什么?

2 个答案:

答案 0 :(得分:3)

x1x2存在差异,这些错误会被log传播并可能更加突出。

max(abs(x1 - x2(1:numel(x1))))
% 1.1102e-16

这是由于浮点数无法表示您的数据完全。有关详细信息,请参阅here

答案 1 :(得分:1)

Per Suever’s answer,这是因为由于不可思议的原因,即使[start : step : stop]和{step和{start,带有浮点step的Matlab结肠运算符stop也会产生非精确结果。 {1}}是相同的,只有import numpy as np np.all(np.arange(0.1,1.0+1e-4, 0.1) == np.arange(0.1, 1.1+1e-4, 0.1)[:-1]) # => True 不同。

这是错的,虽然它不是未知的:在2006年的blog post中(搜索“典型的MATLAB陷阱”),Loren指出: colon运算符可能会受到影响浮点精度问题。

Numpy / Python 做得对:

np.arange(start, stop, step)

stop不包括stop+1e-4,因此我使用上面的all(collect(0.1 : 0.1 : 1) .== collect(0.1 : 0.1 : 1.1)[1:10]) # => true 。)

朱莉娅也是对的:

arange

替代。以下是关于Numpy function y = arange(start, stop, step) %ARANGE An alternative to Matlab's colon operator % % The API for this function follows Numpy's arange [1]. % % ARANGE(START, STOP, STEP) produces evenly-spaced values within the half-open % interval [START, STOP). The resulting vector has CEIL((STOP - START) / STEP) % elements and is roughly equivalent to (START : STEP : STOP - STEP / 2), but % may differ from this COLON-based version due to numerical differences. % % ARANGE(START, STOP) assumes STEP of 1.0. % % [1] http://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html if nargin < 3 || isempty(step) step = 1.0; end len = ceil((stop - start) / step); y = start + (0 : len - 1) * step; 正在做什么的直接猜测,在Matlab中:

step

此函数会尝试将事情保持精确,直到最后一刻,当它按start应用缩放并移动y1 = arange(0.1, 1.0 + 1e-4, 0.1); y2 = arange(0.1, 1.1 + 1e-4, 0.1); all(y2(1:numel(y1)) == y1) % => 1 时。有了这个,你原来的两个向量在它们的共享间隔内是精确的:

log

因此,linspace等所有下游操作也都是精确的。

我将调查Matlab中的 bug 是否导致我们的内部代码出现任何问题,并检查是否应该使用arange强制执行(我相信,但是没有检查过,不会对于精确度问题,或者像上面:而不是arange那样的浮点步骤。 ((stop-start)/step也可能很棘手,因为docs注意,取决于stop,您可能会得到一个向量,其最后一个元素有时大于linspace - 那些相同的文档还建议将form_text_arr = {'text': jQuery("form[name='put_ad_form']").serializeArray()}; 与非单位步骤一起使用。)