忽略 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
注意:如果您的表达式包含函数(如 cos
或 sqrt
等...),它将不起作用。幂运算符 ^
将起作用,并且其优先级也将被覆盖。
像这样就可以了,
调用为:
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
有没有人知道如何让 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
注意:如果您的表达式包含函数(如 cos
或 sqrt
等...),它将不起作用。幂运算符 ^
将起作用,并且其优先级也将被覆盖。
像这样就可以了,
调用为:
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