忽略MATLAB中的数学优先级

时间:2015-02-20 17:55:33

标签: matlab operator-precedence

有没有人知道如何让MATLAB接受字符串假设

f(x)= 3 * x + 5 *(2 + 100),其中x = 5

但是忽略所有优先规则(包括括号)并且仅从左到右计算。 所以上面的答案是140而不是525

我当时认为这将是

[s,r] = strtok(myString,' 0123456789');

进入一个for循环,但我还没有弄清楚到底是怎么做的。

请帮忙! 谢谢

2 个答案:

答案 0 :(得分:0)

嗯,对于一个简单的表达式,一种方法是:

  • 去除所有括号
  • 的表达式
  • 拆分数字和运算符
  • 使用括号重建一个表达式,构造一个严格的从左到右优先级。

当然,在你的情况下,我们首先要处理"函数表达式"的情况。这意味着检测"变量" (在您的情况下为x),并检索它的值。所以建议的代码因此而变得更长。

它适用于您的示例,只要它们尊重相同的样式,就可以适用于不同的表达式。在任何情况下,它只适用于一个变量的功能。

您可能需要添加一些要忽略的字符。目前只会忽略括号(),但您可以添加括号[]以及您的表达式可能包含的任何其他符号,并且您要忽略它们。 (在" Tidy up"段落中添加。)

%% // starting point
myStr = 'f(x) = 3*x + 5*(2+100) ,where x = 5' ;

%% // find "input variables" in the header
strVar = regexp(myStr, '\(([^\)]+)\)' , 'tokens' , 'once' ) ;
strVar = char(strVar) ;  %// =>  strVar='x'

%% // isolate only the function expression (without the header or the x assignation )
ibeg = strfind( myStr , '=' )+1 ;  %// ibeg= 7      find the last position of the expression
iend = strfind( myStr , ',' )-1 ;  %// iend= 23     find the last position of the expression
fstr = myStr(ibeg(1):iend(1)) ;    %// now fstr='3*x+5*(2+100)'   separate only function expression

%% // get the value of the variable at the end of the expression
var  = regexp( myStr(iend:end) , [ strVar '\s*=\s*(\d+)'] , 'tokens' ) ;
%// then replace it in the function expression
fstr = regexprep(fstr, ['(' strVar ')' ] , var{1} ) ; %// Now you function looks like this: "3*5 + 5*(2+100)"

%% // THIS IS THE INTERESTING BIT
%// everything before was only to extract the specific expression

%% // now tidy up
fstr(isspace(fstr)) = [] ;                              %// remove white space characters
idx2remove = [ strfind(fstr,'(') strfind(fstr,')') ];   %// get indices of characters to ignore/remove
fstr( idx2remove ) = [] ;                               %// Now you function looks like this: "3*5+5*2+100"

%% // get the digits and the operators separately
digits = regexp( fstr , '(\d+)' , 'tokens' ) ; %// extract the numbers
oper   = regexp( fstr , '(\d+)' , 'split' ) ;  %// extract the operators
oper   = oper(2:end) ;                         %// remove first empty cell

%% // now rebuild the expression with pure left to right precedence
strFinalFunction = [ '(' char(digits{1}) , char(oper{1}) , char(digits{2}) ')' ] ;
for op = 3:length(digits)
    strFinalFunction = ['(' strFinalFunction char(oper{op-1}) char(digits{op}) ')'] ;
end
%// now your function look like: "((((3*5)+5)*2)+100)"
result = eval( strFinalFunction ) %// then evaluate

注意:如果您的表达式包含函数(如cossqrt等),它将无效。电源操作符^将起作用,其优先级也将被覆盖。

答案 1 :(得分:0)

这样的事情可以解决问题,

请拨打:

StackExchange('f(x) = 3*x + 5*(2+100)', 'x = 5')
StackExchange('3*x + 5*(2+100)', 5)

或两者的任意组合。

function y = StackExchange(f, x)
operations = {'+', '-', '*', '/', '^'};
parenthesis = {'(', ')', '[', ']', '{', '}'};

if ~isnumeric(x)
    x = eval(strrep(strrep(x, 'x', ''), '=', ''));
end

f = strrep(strrep(f, 'f(x)', ''), '=', '');

for h = 1:numel(parenthesis)
    h1 = parenthesis{h};
    f = strrep(f, h1, '');
end

for h = 1:numel(operations)
    h1 = operations{h};

    a = strfind( f , h1);
    for i = length(a):-1:1 ;
        f = [f(1:a(i) - 1), ')', f(a(i):end)] ;
    end

    f = [repmat('(', 1, length(a)), f];
end

f = strrep(f, 'x', num2str(x));
y = eval(f);

end