我基本上试图找到这样一个表达式的产品:
(x-(N-1)/ 2).....(x +(N-1)/ 2)对于N的偶数值
x是我将在开头设置的值也会发生变化,但这是一个不同的问题......
让我们说为了争论,现在x是一个常数(ex x = 1)
N = 6
的例子(X-5/2)(X-3/2)(X-1/2)(X + 1/2)(X + 3 / 2)*(X + 5/2)
这个想法是创建一个行向量,每个元素都是每个单独的术语(P(1)= x-5/2)(P(2)= x-3/2)...等然后计算它的产品
N=6;
x=1;
P=ones(1,N);
for k=(-N-1)/2:(N-1)/2
for n=1:N
P(n)=(x-k);
end
end
y=prod(P);
相反,这会创建一个仅占用epxression的第一个值的向量 在每个细胞重复相同的值。
我的循环显然存在根本问题,但我无法看到它。
因此,如果任何人都可以提供帮助或建议更好的方法来计算产品,我将不胜感激。
答案 0 :(得分:2)
为什么在使用prod
等矢量化命令时使用循环?
y = prod(2 * x + [-N + 1 : 2 : N - 1]) / 2;
为方便起见,您可能希望为其定义匿名函数:
f = @(N,x) reshape(prod(bsxfun(@plus, 2 * x(:), -N + 1 : 2 : N - 1) / 2, 2), size(x));
请注意,该函数与(行或列)向量输入x
兼容。
>> f(6, [2,2]')
ans =
-14.7656
4.9219
-3.5156
4.9219
-14.7656
>> f(6, [2,2])
ans =
-14.7656 4.9219 -3.5156 4.9219 -14.7656
以下是rayreng's approach与我的比较。前者成为明显的赢家...... :'(
......至少随着N的增加而增加。
function benchmark
% varying N, fixed x
clear all
n = logspace(2,4,20)';
x = rand(1000,1);
tr = zeros(size(n));
tj = tr;
for k = 1 : numel(n)
% rayreng's approach (poly/polyval)
fr = @() rayreng(n(k), x);
tr(k) = timeit(fr);
% Jubobs's approach (prod/reshape/bsxfun)
fj = @() jubobs(n(k), x);
tj(k) = timeit(fj);
end
figure
hold on
plot(n, tr, 'bo')
plot(n, tj, 'ro')
hold off
xlabel('N')
ylabel('time (s)')
legend('rayreng', 'jubobs')
end
function y = jubobs(N,x)
y = reshape(prod(bsxfun(@plus,...
2 * x(:),...
-N + 1 : 2 : N - 1) / 2,...
2),...
size(x));
end
function y = rayreng(N, x)
p = poly(linspace(-(N-1)/2, (N-1)/2, N));
y = polyval(p, x);
end
function benchmark2
% fixed N, varying x
clear all
n = 100;
nx = round(logspace(2,4,20));
tr = zeros(size(n));
tj = tr;
for k = 1 : numel(nx)
disp(k)
x = rand(nx(k), 1);
% rayreng's approach (poly/polyval)
fr = @() rayreng(n, x);
tr(k) = timeit(fr);
% Jubobs's approach (prod/reshape/bsxfun)
fj = @() jubobs(n, x);
tj(k) = timeit(fj);
end
figure
hold on
plot(nx, tr, 'bo')
plot(nx, tj, 'ro')
hold off
xlabel('number of elements in vector x')
ylabel('time (s)')
legend('rayreng', 'jubobs')
title(['n = ' num2str(n)])
end
function y = jubobs(N,x)
y = reshape(prod(bsxfun(@plus,...
2 * x(:),...
-N + 1 : 2 : N - 1) / 2,...
2),...
size(x));
end
function y = rayreng(N, x)
p = poly(linspace(-(N-1)/2, (N-1)/2, N));
y = polyval(p, x);
end
或者,因为您的产品中的术语形成了算术级数(每个术语比前一个术语大1/2),您可以使用the formula for the product of an arithmetic progression。
答案 1 :(得分:1)
我同意@Jubobs的意见,你应该避免使用for
循环进行这种计算。有些情况下for
循环执行速度很快,但对于这样简单的事情,请尽可能避免使用循环。
Jubobs建议的另一种方法是,您可以将多项式方程视为因子形式,其中每个因子表示位于该特定位置的根。您可以使用poly
将这些因子转换为多项式方程,然后使用polyval
来计算所需点的表达式。首先,按linspace
生成根,其中点从-(N-1)/2
到(N-1)/2
不等,并且有N
个,然后将其插入poly
。最后,对于x
的任何值,将其放入polyval
并输出poly
。这种方法的优点是您可以在一次扫描中评估x
的多个点。
继续你所拥有的,你只需要这样做:
p = poly(linspace(-(N-1)/2, (N-1)/2, N));
out = polyval(p, x);
以您的示例为例,假设N = 6
,这将是第一行的输出:
p =
1.0000 0 -8.7500 0 16.1875 0 -3.5156
因此,这就是说当我们扩展(x-5/2)(x-3/2)(x-1/2)(x+1/2)(x+3/2)(x+5/2)
时,我们得到:
x^6 - 8.75x^4 + 16.1875x^2 - 3.5156
如果我们看一下这个等式的roots
,这就是我们得到的:
r = roots(p)
r =
-2.5000
2.5000
-1.5000
1.5000
-0.5000
0.5000
正如您所看到的,每个术语对应于多项式方程中的一个因子,因此我们在这里有正确的思维方式。现在,您只需使用p
将x
的值polyval
用于-2 <= x <= 2
即可获得结果。例如,如果我想评估来自x
的多项式,其中polyval(p, -2:2)
ans =
-14.7656 4.9219 -3.5156 4.9219 -14.7656
是一个整数,这就是我得到的结果:
x = -2
因此,当-14.7656
时,结果为{{1}},依此类推。
答案 2 :(得分:1)
虽然我会推荐@Jubobs的解决方案,但检查循环问题也很好。
第一个指示错误的指示是,您有一个嵌套循环超过2个变量,并且仅使用其中一个索引来存储结果。可能你只需要一个循环。
这是一个您可能感兴趣的循环,应该大致按照您的需要进行:
N=6;
x=1;
k=(-N-1)/2:(N-1)/2
P = ones(size(k));
for n=1:numel(k)
P(n)=(x-k(n));
end
y=prod(P);
我试图让代码接近原始代码,所以希望它很容易理解。