我注意到例如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个条目时,行为似乎就开始了。
虽然差异非常小,但是当使用大型向量进行大量操作缩放时,错误变得非常大,值得注意。
有没有人知道这里发生了什么?
答案 0 :(得分:3)
x1
和x2
存在差异,这些错误会被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()};
与非单位步骤一起使用。)