开发者问题收集

评估MATLAB中的恒定表达

2021-04-26
197

我目前正在编写一个脚本,该脚本从用户那里获取一个函数和间隔,然后使用梯形法计算积分。该脚本还会计算误差。为此,我需要使用输入函数的二阶导数。如果二阶导数为常数或 0,则会出现“输入参数过多”错误。以下是一小段代码,用于说明错误发生的位置:

%integrate x^2 from 0 to 5
syms x
func = x^2;
deriv = diff(func,x,2);
func = matlabFunction(func);
deriv = matlabFunction(deriv);
deriv(0:0.01:5); %<- error since deriv = 2, needed to compute the error on the trapezoid method.

matlab 是否有办法计算向量 0:0.01:5,并返回一个大小相同的向量,每个传递的值均为“2”?函数导数是否为常数尚不清楚,取决于用户输入的内容。

2个回答

听起来,一个逻辑结构应该足以解决这个问题。然而,开发它的挑战来自于必须在三 (3) 种数据类型( doublesymchar )之间进行权衡。我找不到更简洁的方法,但这应该可以解决这个问题(请参阅下面的解释以了解详情):

syms x
func = x^2;
deriv = diff(func,x,2);
IN = *input vector*; %User-defined input vector.
N = length(IN); %Get length of input vector.
algebra = char(deriv); %Convert algebraic expression "deriv" to character array.
[num,status] = num2str(algebra); %Check to see if "deriv" is algebraically equivalent to a constant.
if status == 1 %If so
    deriv = num*ones(N,1) %Extract its value and copy it along a vector of the same length as the input
else %Run your code essentially.
    func = matlabFunction(func);
    deriv = matlabFunction(deriv);
    deriv(0:0.01:5);
end

注意: 从现在开始, x = sym('x')

假设用户定义表达式 f = 3*x^3 ,然后对其调用 diff ,因为 der = diff(f,x) 应该输出 der=9*x^2 。由于这是一个非零导数,因此您将继续使用梯形规则算法。但是,假设 f = 2 ,调用此新 f 的 diff 函数的结果将是 der = 0 注意 :当 diff 对结果为常量的表达式进行微分时,输出将被视为 sym 对象。在此示例中, 0sym 对象,而不是 double 。要将其转换为 double ,可以考虑将其强制转换为 c = double(der) 。问题是, double() 没有处理 der 仍然是代数表达式的情况的功能(即,如果 der = 3*x ,则 double(der) 返回错误)。但是,函数 char() 可以处理这种情况。实际上,它应该能够将任何 sym 表达式转换为 char 数组。这样就可以使用 str2num() 函数,该函数有一个可选参数,用于确定是否可以进行字符串到双精度(或 char 到双精度)的转换。语法为: [num,status] = str2num(char(der)) 。如果 der =3*x ,则 char(der) = '3*x'num = []status = 0 。然而,对于常数导数的情况,比如 der = 3 ,那么 char(der) = '3' ,然后 num = 3 ,并且 status = 1

J.A. Ferrand
2021-04-26

@J.A. Ferrand:我无法在您的答案下发表评论(声誉太低),但您提供的解决方案有一个明显的错误。我们应该使用 str2num ,而不是代码第 7 行中的 num2str

下面我根据 J.A. Ferrand 的解决方案提供我自己的解决问题的方法。

将常量代数表达式转换为函数句柄是有问题的,因为在这种情况下 matlabFunction 无法“猜测”函数变量的数量以及它们的名称。但是,如果您处理的是具有一定数量输入变量的函数(例如:一个),下面是 matlabFunction 的“改进”版本。

function fh = matlabFunctionImproved(symExp)

% This is an improved version of matlabFunction function,
% that circumvents an "inconvenient" behaviour of the original function
% in case of constant argument.
% Remark: This function works properly only for single-valued functions.
    
charExp = char(symExp)  % Convert algebraic expression to character array.
[num,status] = str2num(charExp) ;  % Check to see if symExp is algebraically equivalent to a constant.

  if status == 1 %If so
    fh = @(x) num * ones(size(x)) ; %Extract its value and copy it along a vector of the same length as the input
  else % Run your code essentially.
    fh = matlabFunction(symExp);
  end

end

如果要使用两个或更多变量的函数,则可以修改所提供的代码...

Martin
2023-08-01