eval
和str2func
都能够评估字符串f.e表示的函数。 f='a^x+exp(b)+sin(c*x)+d'
:
使用eval
:
y = eval(f)
或(由rahnema1建议)
fHandle = eval(['@(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
使用str2func
:
fHandle = str2func(['@(x, a, b, c, d) ' f]);
y = fHandle(x, a, b, c, d);
哪种方法都具有最佳性能?
说明
请注意,此基准测试的灵感来自this question。
答案 0 :(得分:6)
简答:使用str2func
。
<强>基准强>
基准测试将评估N
的{{1}}个不同值的函数。
x
f='a^x+exp(b)+sin(c*x)+d';
Ns = linspace(1, 1000, 20);
timeEval = zeros(size(Ns));
timeEvalHandle = zeros(size(Ns));
timeStr2func = zeros(size(Ns));
for i=1:length(Ns)
N = Ns(i);
timeEval(i) = timeit(@() useEval(f, N));
timeEvalHandle(i) = timeit(@() useEvalHandle(f, N));
timeStr2func(i) = timeit(@() useStr2func(f, N));
end
figure
plot(Ns, timeEval, 'DisplayName', 'time eval');
hold on
plot(Ns, timeEvalHandle, 'DisplayName', 'time eval');
hold on
plot(Ns, timeStr2func, 'DisplayName', 'time str2func');
legend show
xlabel('N');
figure
plot(Ns, timeEval./timeStr2func, 'DisplayName', 'time_{eval}/time_{str2func}');
hold on
plot(Ns, timeEvalHandle./timeStr2func, 'DisplayName', 'time_{eval handle}/time_{str2func}');
legend show
xlabel('N');
figure
plot(Ns, timeEvalHandle./timeStr2func);
ylabel('time_{eval handle}/time_{str2func}')
xlabel('N');
function y = useEval(f, N)
a = 1; b = 2; c = 3; d = 4;
for x=1:N
y = eval(f);
end
end
function y = useEvalHandle(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = eval(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
function y = useStr2func(f, N)
a = 1; b = 2; c = 3; d = 4;
fHandle = str2func(['@(x, a, b, c, d) ' f]);
for x=1:N
y = fHandle(x, a, b, c, d);
end
end
vs str2func
(没有函数句柄):结果显示即使对函数进行一次评估,使用{{1}也要快50%左右比eval
(没有函数句柄)。对于大量评估,str2func
可能快约100倍(取决于您正在评估的功能)。
eval
vs str2func
(带功能句柄): str2func
对于单次评估比eval
慢约100%,但变为对于大量评估来说几乎同样快(eval
慢了约5%)。
str2func
:请注意,对于单个评估,使用eval
创建函数句柄比直接评估它要慢约50%。
结论: eval
总是比eval
快。
答案 1 :(得分:1)
在以下基准测试中,创建了一组函数句柄,并将eval
的性能与str2func
的性能进行比较以评估字符串。函数是带有+符号的变量的组合。
n = 16;
op=char((dec2bin(0:2^n-1)-48)*2+43);
vars= 'a':'z';
v = vars(1:n+1);
s(1:2^n,1:2:2*n+1)=repmat(v,2^n,1);
s(:,2:2:end)=op;
h=repmat(['@(' sprintf('%c,',v(1:end-1)) v(end) ')'],2^n,1);
farray=[h,s];
tic
for k = 1:2^n
f = eval(farray(k,:));
end
toc
tic
for k = 1:2^n
f = str2func(farray(k,:));
end
toc
八度结果:
两种方法没有区别。