忽略 MATLAB 中的数学优先级

Disregard mathematical precedence in MATLAB

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

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

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

我在想应该是

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

放入一个 for 循环,但我一直无法弄清楚具体如何去做。

请帮忙! 谢谢

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

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

当然你的情况我们也首先要处理"function expression"的情况。这意味着检测 "variable" (在您的情况下为 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 等...),它将不起作用。幂运算符 ^ 将起作用,并且其优先级也将被覆盖。

像这样就可以了,

调用为:

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