Function 在matlab中求常数表达式

Function 在matlab中求常数表达式,function,matlab,Function,Matlab,我目前正在编写一个脚本,从用户那里获取函数和间隔,然后使用梯形方法计算积分。脚本还计算错误。为此,我需要使用输入函数的二阶导数。在二阶导数是常数或0的情况下,我得到了输入参数过多的错误。下面是代码的一小部分,以说明错误发生的位置: %integrate x^2 from 0 to 5 syms x func = x^2; deriv = diff(func,x,2); func = matlabFunction(func); deriv = matlabFunction(deriv); deri

我目前正在编写一个脚本,从用户那里获取函数和间隔,然后使用梯形方法计算积分。脚本还计算错误。为此,我需要使用输入函数的二阶导数。在二阶导数是常数或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.
%x^2从0集成到5
符号x
func=x^2;
deriv=diff(func,x,2);
func=matlabFunction(func);
deriv=matlabFunction(deriv);

德里夫(0:0.01:5);% 从听起来,逻辑结构应该足以解决这个问题。然而,开发it的挑战在于必须在三(3)种数据类型之间进行转换(
double
sym
char
)。我找不到更简洁的方法,但这应该可以解决这个问题(请参阅下面的解释以了解更多信息):

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


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

我想我找到了一个可能的解决方案,但我希望人们确认,当函数不是常数时,这确实不会导致意外的后果。如果我做的是
deriv=matlabFunction(deriv,'Vars',x)
,那行吗?如果你使用符号数学,你应该使用符号数学来计算积分。符号数学只是推导函数,然后大部分计算都是通过代换值来完成的。如果我使用符号数学,将需要大量的sub,这将增加计算时间。在代码的某些部分,每次新的迭代似乎都要花费指数级的时间来计算,一次迭代几乎不花费时间,接下来的几秒钟和之后的几分钟(不知道为什么,但将其隔离到subs函数)。将它们转换为数值似乎是最好的做法,因为有些需要数千次迭代。还有一点我忘了提到,积分本身的值不是脚本的主要目的,而是专门应用梯形方法。这是我正在学习的一门关于数值方法的课程。因此,使用内置的积分函数可以克服计算时间过长的问题,但这似乎与您的问题无关,因为您根本不谈论计算时间,也不使用
subs
。我仍然认为您需要跳过
matlabFunction
。如果您不想使用
vpaintegral
,因为您想手动进行数值积分,那么使用
double(subs(deriv,0:0.01:5))
获取采样函数。对于你的例子,这只需要一小段时间。感谢你花时间回复,我会尝试一下你的方法,但我发现一些似乎有效的方法。我不知道它到底起什么作用,但它似乎起到了我想要的作用(我不知道在一些边缘病例中是否有副作用,也许你有?)。如果我在我的代码中将deriv=matlabFunction(deriv)
替换为
deriv=matlabFunction(deriv,'Vars',x)
,我现在可以通过执行
deriv(0:0.01:5)来计算常量函数。这会导致任何问题吗?或者这是一个有效的解决方法吗?我刚刚运行了您的代码以及您在上一次评论中提出的修改。在我看来,
deriv
作为
1by1 double
返回,这意味着它不是行向量,而是标量。如果你需要一个2的行向量,那么在我看来至少这并不能解决问题。老实说,我对
matlabFunction()
不太熟悉,因此我无法提供我希望的更多见解。非常感谢,您已经帮了我很多忙。我没有意识到函数返回了1x1双精度,但它仍然比错误好。我会考虑到这一点来解决问题。我在考虑创建一个与输入大小相同的向量,填充1,然后将向量中的每个元素乘以2。在matlabFunction()不是常数的情况下,它将返回一个向量,并将该向量乘以1的向量将得到相同的向量;在matlabFunction()是常数的情况下,它将创建一个新的常数向量。那行吗?原则上行。我在上面发布的答案中就是这么做的。找线<
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