Problem with str2func and error with valid function name

I have to concatenate a defined number of strings into one, then to convert this string into a function that I memorize. Then I have to give input to this new function to calculate many values.
As you'll see below I use str2func to do that. When I test this function, Matlab warns me that my function is unvalid, so my program doesn't work right at its beginning, however after many tries I don't know which other way to use.
Here is the code
function [value]=squareAndSum(stringFunc,x,y)
%x and y are two vectors, stringFunc the string we want to convert %into a function
%this function must calculate the value of this new fonction for %each y and use it to update value
value=0;
totalDots=length(y);
fh=str2func(stringFunc);
yApprox=zeros(totalDots);
for i=1:1:totalDots
yApprox(i)=fh(x(i));
squared=(y(i)-yApprox(i))*(y(i)-yApprox(i));
value=value+squared;
end;
When I test it with x=[1 ; 2 ; 3 ; 4], y=[5 ; 6 ; 7 ; 8] and stringFunc = '2*cos', Matlab displays :
Warning: The input to STR2FUNC "2*cos" is not a valid function name. This will generate an error in a future release.
> In squareAndSum at 6
??? Undefined function or method '2*cos' for input arguments of type 'double'.
Error in ==> squareAndSum at 9
yApprox(i)=fh(x(i));
With stringFunc = 'cos' however it works, of course, but I really need to concatenate different strings to create a new function for my work. (and I have very little time...)
Sorry if the question seems rather simple, I am quite new with Matlab.
Thanks in advance for your help

 採用された回答

Walter Roberson
Walter Roberson 2012 年 2 月 11 日

1 投票

but note that that will only work if you have a defined variable name to apply the function to, which you do not have in the case of '2*cos' so you will need to consider passing a different string as stringFunc

9 件のコメント

A R
A R 2012 年 2 月 11 日
So, instead of using only '2*cos', I should do :
fh=(stringFunc + 'x(i)');
and then affect to y this fh in the loop like this
fh=str2func(stringFunc+'x(i)');
yApprox=zeros(totalDots);
for i=1:1:totalDots
yApprox(i)=fh(x(i));
squared=(y(i)-yApprox(i))*(y(i)-yApprox(i));
value=value+squared;
end;
Or should I affect the x(i) another way ?
A R
A R 2012 年 2 月 11 日
Sorry I've made a copy/paste error, I'd rather mean in the loop :
yApprox = fh;
A R
A R 2012 年 2 月 11 日
after having included the expression of fh into the loop
Walter Roberson
Walter Roberson 2012 年 2 月 11 日
If you tack on the 'x(i)' on the end, then what are you going to do if the passed string is (say) 'sin + cos' ? And if the function desired to apply is (say) 3 * x^2 + 2 * cos(x) + x then what string should the user pass in? '3*^2+2*cos+' perhaps ??
You are constructing an anonymous function. The variable is a "dummy variable" just like your variable "stringFunc" is a dummy variable for the purpose of your function: that is, it acts as a place holder for a value being passed in. The value being passed in will be x(i), but that doesn't mean that your dummy variable name should be x(i) -- indeed, that is not a valid dummy variable name. A dummy variable name has to be a simple variable name.
http://www.mathworks.com/help/techdoc/matlab_prog/f4-70115.html
Walter Roberson
Walter Roberson 2012 年 2 月 11 日
yApprox = fh;
would mean that you want to copy the function handle _itself_ to yApprox.
Your earlier syntax was correct:
yApprox(i)=fh(x(i));
would mean apply the function handle stored in the variable fh, to the argument x(i)
Walter Roberson
Walter Roberson 2012 年 2 月 11 日
It is nearly 3AM here, and I need to go to sleep.
Have the string passed down _already_ include the variable name 'x'. Do not tack anything at all on to the end of the string. Just put the '@(x)' on to the beginning of the string, and make the result in to an anonymous function. As noted in the link I gave earlier, if you have a new enough MATLAB version you can do that by applying str2func() to the overall string, if you have an older MATLAB you will need to eval() the string.
fh - str2func(['@(x) ' stringFunc]);
In the loop,
yApprox(i) = fh(x(i));
To use this, the user would pass down (e.g.) '2*cos(x)' . If there is no 'x' variable in what the user passes down and what the user passes down does not evaluate to a constant, then there will be problems. Which means you should probably put in a try/catch block around the function evaluation.
Walter Roberson
Walter Roberson 2012 年 2 月 11 日
Above, the line
fh - str2func(['@(x) ' stringFunc]);
should be
fh = str2func(['@(x) ' stringFunc]);
A R
A R 2012 年 2 月 11 日
Yes, I noticed but thanks a lot !
In fact, this precise expression doesn't seem to work but I explore your link, I am testing the void parenthesis
Walter Roberson
Walter Roberson 2012 年 2 月 11 日
Remember if you do not have a new enough MATLAB version then you need to use eval instead of str2func:
fh = eval(['@(x) ' stringFunc '(x)']);

サインインしてコメントする。

その他の回答 (4 件)

Walter Roberson
Walter Roberson 2012 年 2 月 11 日

0 投票

If your government has not asked the Canadian Embassy to contact me, then this isn't an emergency.

1 件のコメント

A R
A R 2012 年 2 月 11 日
Sorry for this word
Anyway could you help ?

サインインしてコメントする。

A R
A R 2012 年 2 月 11 日

0 投票

After these first answers, I understand that the problem is that I don't really see how to define x(i) as the variable which enable to calculate 2*cos(x(i))
I tried this :
function [value]=squareAndSum(stringFunc,x,y)
%x and y are two vectors
value=0;
totalDots=length(y);
yApprox=zeros(totalDots);
for i=1:1:totalDots
newString=[stringFunc '(x(i))'];
fh=str2func(newString);
yApprox(i)=fh;
squared=(y(i)-yApprox(i))*(y(i)-yApprox(i));
value=value+squared;
end;
But the message is the same because this time, x(i) is understood as a part of the expression of the new function
A R
A R 2012 年 2 月 11 日

0 投票

To Walter Roberson :
yes, I want to do something like that except that it is more simple : the variable x is always at the end. Taking something close to your example, it would be '3^2+2*cos' gives 3^2+2*cos(x), you see x will be always the last one included
I understood most of your explanation, but if my syntax is correct, does it means, as you've just said, that it is not my dummy function but my dummy variable which is unvalid ?
So I should name (say) variable = x(i) and then do yApprox = fh(variable);
?

2 件のコメント

A R
A R 2012 年 2 月 11 日
I've just tested and this doesn't work either...
Walter Roberson
Walter Roberson 2012 年 2 月 11 日
If you only have one x and it is at the end, then
fh = str2func(['@(x) ' stringFunc '(x)']);
You would not use @()
You do not need to assign x(i) to a variable:
yApprox(i)=fh(x(i));

サインインしてコメントする。

A R
A R 2012 年 2 月 11 日

0 投票

I finally figured it out !! Thank you very much Walter Roberson !
Here is the corrected code :
function [value]=squareAndSum(stringFunc,x,y)
%x and y are two vectors
value=0;
totalDots=length(y);
yApprox=zeros(totalDots);
for i=1:1:totalDots
newString = [stringFunc '(x)'];
fh = str2func(['@(x)' newString]);
yApprox(i) = fh(x(i));
squared=(y(i)-yApprox(i))*(y(i)-yApprox(i));
value=value+squared;
end;
which gives with my previous example :
>> squareAndSum(stringFunc, x,y)
ans =
229.3076
Thanks again !

カテゴリ

ヘルプ センター および File ExchangeCharacters and Strings についてさらに検索

質問済み:

A R
2012 年 2 月 11 日

編集済み:

2013 年 10 月 8 日

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by