函数作业

澳大利亚程序代写 使用一些数值方法来实现和积分函数。 您将编写一个程序“numerics”,它从标准输入中读取命令。 首先,有两个命令:define和test…

使用一些数值方法来实现和积分函数。

 

步骤1:解析函数 澳大利亚程序代写

————————-

您将编写一个程序“numerics”,它从标准输入中读取命令。

首先,有两个命令:define和test

看起来像这样:

define(f x y z)=(+(*x y)(-z 3))

test (f 3 4.2 5)14.6

test(f-19.2 6)-6.2

对于此输入,程序应输出:

Defined f(x y z)

f(34.25)=14.6[correct]

f(-19.26)=-6.2[correct]

具体来说,define后面必须跟(id id…)

标识符(id)是一系列字母(大写和/或小写,区分大小写)和数字,必须以字母开头。

第一个id是所定义函数的名称。任何剩余的id都是该函数的参数名。

在上面的第一行中,我们定义了一个名为“f”的函数,它包含3个参数:“x”、“y”和“z”。所有函数都必须至少接受一个参数,但数字没有上限(因此可以生成一个接受100、1000或10000个参数的函数)。

下一个必须是=符号,后跟表达式。表达式是下列表达式之一:

-函数调用:(fname expr…)

fname可以是id(指定用户定义的函数),也可以是+,-,*,%,/,^指定内置的数学运算。注意,与C不同,^是power。使用数学库中的内置pow函数。

-参数名:id

-数字常量:strtod接受为有效双精度数的字符序列

 

例如,(f 3 4 5.2)是表达式,因为3、4和5.2是表达式,所以(f3 4 5.2)是(id expr expr expr expr)。

所有函数名(括号中的第一个标识符)必须引用以前定义的函数,而所有其他标识符必须引用此函数的参数或是数字常量。

试图重新定义已定义的函数时出错。

注意,任意数量的空格可能出现在任何标记(id、fname、parens、数值常量)之间(但不在其内部),而不会改变其含义。

例如 澳大利亚程序代写

(f 3 4 5)

( f             3       4  5    )

含义一样。但是 (fx yz)和(f x y z)两者有两种含义(前者用一个参数“y z”调用函数“f x”,后者用三个参数“x”、“y”和“z”调用函数“f”)。

 

test有两个参数。第一个必须是不带变量的表达式——它们可以引用函数,并具有参数的数值常量。但是,它们可以调用其他函数。下列都是有效的(假设F、G1、G2和H的适当定义存在):

test(f 3 4.2 5)14.6

test(f(g1 1 2)(g2 3 4)(h 5 6-7))99.87

 

第二个参数是要计算到的表达式的预期值。test命令应计算其第一个参数,并与第二个参数进行比较。

-第二个参数是数字常量或者任意表达式,例如test(f 1 23)(g 4 5)

当程序执行测试语句时,其行为取决于求值是否与预期结果匹配。如果有,它会输出:

f(3 4.2 5)=14.6[correct](即,表达式=值[correct])

如果没有,输出

(g 1 2)=55.6[incorrect:expected-99.8] (即,表达式=实际值[incorrect:expected]

 

注意:不应将浮点数与==进行比较。如果这样做,例如sqrt(2)*sqrt(2)==2,将得到“false”(由于舍入的工作方式,最终得到sqrt(2)*sqrt(2)是2.00000000000000044)。相反,如果abs(期望值-实际值)<0.0000000000001,将认为测试通过

 

内置的数学运算(+,-,*,/,%)的含义与C中的相同(和^与pow相同)。

 

还应该提供以下内置函数(这些名称应该是预定义的): 澳大利亚程序代写

floor

ceil

round

logb

select

 

其中,floor、ceil和round使用一个参数,并且其行为与数学库中的行为完全相同(使用数学库)。

 

logb函数接受两个参数,并计算第二个参数指定的基数中第一个参数的对数。那就是

(logb 16 2) 会计算为4,因为16的对数(基2)是4,,,,,log(lhs)/log(rhs)

 

select函数接受三个参数test、t和f。如果test>=0,则select计算其第二个参数(t),否则计算其第三个参数(f)。

 

例如,可以将绝对值函数定义为

define(abs x)=(select x x(-0 x))

 

#符号表示行末的注释。例如

 

#define xy+z-3 function

define(f x y z)=(+(*x y)(-z 3))

test(f 3 4.2 5)14.6  #other comments

test(f-19.2 6)-6.2

 

如果输入无效或测试失败,程序应打印错误消息并继续执行下一行输入。

第二步:数值积分 澳大利亚程序代写

—————————–

下一步是使用梯形方法添加对数值积分的支持。回想一下微积分,一个函数的定积分是它在一定范围内曲线下的面积。近似这个积分的一种方法是计算许多梯形的面积(每个高度是梯形的左右两边的函数的值),并对它们的面积求和。用足够小的梯形,实际面积的近似是相当好的。对于每个梯形,面积为

(f(x)+f(x+width))/2*width

这一原理推广到多维,其中积分在2个参数的函数下计算体积,其中一个特定“切片”的体积为:

(f(x,y)+f(x+width,y)+f(x,y+width)+f(x+width,y+width))/4*width*width

澳大利亚程序代写
澳大利亚程序代写

另一种方法是矩形棱镜,其高度是切片四个角的平均值。同样的想法也适用于任何维数。

要添加此功能,您将添加对新命令“numint”(数字积分的缩写)的支持。

numint命令采用的参数数量取决于它正在积分的函数所需的参数数量。

1.第一个参数将始终是已定义函数的名称

2.第二个参数是“步长”(即每个矩形的宽度)。

3.其余的参数成对出现,指定每个参数的积分范围。每个参数必须有一个范围(一对数字)。

 

例如:

define(f x y)=(+(*2 x)y)

numint f 0.001-1 1 4 5

这将计算f(x,y)=2*x+y曲线下的体积,x从-1到1,y从4到5。它将通过求出2000000个矩形棱柱体的体积(每个棱柱体的长度为0.001,宽度为0.001)和基于该特定矩形左/右处f的平均值的高度的总和来计算。

 

步骤3:蒙特卡罗积分

——————————-

第三步是添加对“mcint”(Monte Carlo Integration)命令的支持。这个命令近似于曲线下的面积(或体积等),但不是用许多矩形的体积求和,而是使用蒙特卡洛方法。

 

特别是,它在积分范围内选取许多随机点。然后,它使用这些来估计该区间内曲线的平均值。也就是说,如果函数是y=f(x),然后计算:

f(x1) + f(x2) + …f(xN)

y_avg = ————————

N

area = y_avg * (xmax – min)

 

对于三维曲线 (z = f(x,y)) :

f(x1,y1) + f(x2,y2) + … f(xN,yN)

z_avg = ———————————-

N

volume = z_avg * (xmax – xmin) * (ymax – ymin)

 

对于高维曲线,同样的想法也适用。

“mcint”的参数与“numint”相同,只是第二个参数是试验次数(要选择的随机点数)而不是步长。第一个参数仍然是函数名,其余的参数仍然是要积分的范围。

 

第四步:梯度上升 澳大利亚程序代写

———————–

最终任务是添加命令来查找最大值(“max”命令)或最小值(“min”命令),通过梯度上升或下降。

带多个输入的数学函数的梯度是导数在多维中的推广。我们将在这里考虑二维情况(尽管这一概念推广到任何数量的维度)。对于具有两个输入x和y的函数(f),梯度(Df)是其输出为二维向量的函数。也就是说,Df(x,y)是指向f在点(x,y)处具有最大增长率的方向的向量,其大小是图在该方向上的斜率。函数的梯度可以通过取函数对每个分量的偏导数来计算。也就是说,向量的x分量是d f(x,y),y分量是df(x,y)。

 

以同样的方式,我们可以数值近似在一个特定的点的任意函数的导数,我们可以数值近似在特定点的任意函数的梯度。梯度可以用于数值求函数的局部最大值或最小值。我们可以通过使用梯度上升(找到最大值)或梯度下降(找到最小值)来实现这一点。梯度上升的工作原理是从一个特定的点开始,然后沿着当前点上的梯度向量进行迭代改进。

 

也就是说,如果我们目前在pcurr,我们选择下一个点pnew=pcurr+gamma*Df(pcurr),其中gamma是我们按比例缩放渐变的某个因子。在最简单的梯度上升形式中,gamma是常数,尽管使用gamma的自适应值可以提高算法的收敛速度。注意,梯度下降的工作方式几乎相同,但与梯度相反,在上面的方程中,用a-代替+表示。这个过程在它收敛时结束,也就是说,当pnew完全接近pcurr时,我们的答案是足够好的(当我们接近局部最大值时,它们将更接近于“函数”,其中梯度将是(0, 0))。

 

这里,f是想要最大化的二维函数,startPoint有(x,y)坐标,从它开始上升,gamma是在更新当前点时缩放梯度的常数,收敛距离convergedDistance是pcurr和pnew之间的距离,在这里我们认为算法收敛了。它们之间的距离小于收敛距离,我们认为pnew是“足够接近”,为正确答案。

 

命令应采用以下参数:

1.函数的名称

2.gamma

3.收敛距离convergedDistance

4.起始点startPoint,它的数字和函数的参数一样多。

5.在放弃和决定上升/下降不收敛之前要采取的最大步骤数。

 

例如,如果定义了f

define(f x y)=(+(^x 2)(^y 2)(+(*4 x)1)

然后

min 0.1 0.0001 3 1000

应该输出

(2,0)或(2.0,0.0)