MFP编程语言对于各种数学和科学计算的支持:
前面已经介绍了MFP语言基本运算操作符(包括加减乘除等),以及用solve语句解方程,这一章将侧重于介绍MFP语言所提供的进行各种数学计算的函数。
第1节 内置的数学常用变量
前面的章节已经介绍了MFP一些内置的变量包括虚数单位i,空值null以及无定义数nan和nani。为了方便进行数学计算,MFP还内置了
1. 代表无穷大的变量inf,这个变量表示实数正无穷大。显然,-inf表示实数负无穷大。
2. 代表虚数无穷大的变量infi,这个变量表示在虚轴正方向上的无穷大,显然,在虚轴负方向上的无穷大为-infi。
之所以定义这个变量是因为虚轴上的无穷大是无法通过inf和i相乘得到(它们的乘积等于nan+infi),所以必须用一个特别的变量来定义。
3. 代表圆周率的变量pi,它的值等于3.1415926535897932384626433832795028841971693993751058209749445923。
4. 代表自然对数的变量e,它的值等于2.7182818284590452353602874713526624977572470936999595749669676277。
以上的这些变量常常用于下面所介绍的函数的参数。
第2节 单位转换函数和返回物理化学常量值的函数
MFP语言提供了单位转换函数convert_unit。convert_unit(value, from_unit, to_unit)将基于某一个单位的数值转换为基于另外一个单位的数值。第一个参数是将要转换的数值,第二个参数是将被转换的单位(单位是一个对大小写敏感的字符串),第三个参数是转换后的单位(单位是一个对大小写敏感的字符串)。比如,convert_unit(23.71,"m","km")返回0.2371。
本函数支持以下单位:
1.长度单位:"um"(微米),"mm"(毫米),"cm"(厘米),"m"(米),"km"(公里),"in"(英寸),"ft"(英尺),"yd"(码),"mi"(英里),"nmi"(海浬),"AU"(天文单位),"ly"(光年),"pc"(秒差距);
2.面积单位:"mm2"(平方毫米),"cm2"(平方厘米),"m2"(平方米),"ha"(公顷),"km2"(平方公里),"sq in"(平方英寸),"sq ft"(平方英尺),"sq yd"(平方码),"ac"(英亩),"sq mi"(平方英里);
3.体积单位:"mL"(毫升),"L"(升),"m3"(立方米),"cu in"(立方英寸),"cu ft"(立方英尺),"cu yd"(立方码),"km3"(立方公里),"fl oz(Imp)"(液盎司(英制)),"pt(Imp)"(品脱(英制)),"gal(Imp)"(加仑(英制)),"fl oz(US)"(液盎司(美制)),"pt(US)"(品脱(美制)),"gal(US)"(加仑(美制));
4.质量单位:"ug"(微克),"mg"(毫克),"g"(克),"kg"(千克),"t"(吨),"oz"(盎司),"lb"(磅),"jin"(市斤),"jin(HK)"(斤(香港)),"jin(TW)"(台斤);
5.速度单位:"m/s"(米每秒),"km/h"(千米每小时),"ft/s"(英尺每秒),"mph"(英里每小时),"knot"(节);
6.时间单位:"ns"(纳秒),"us"(微秒),"ms"(毫秒),"s"(秒),"min"(分钟),"h"(小时),"d"(天),"wk"(礼拜),"yr"(年);
7.力单位:"N"(牛顿),"kgf"(千克力),"lbF"(磅力);
8.压强单位:"Pa"(帕斯卡),"hPa"(百帕),"kPa"(千帕),"MPa"(兆帕),"atm"(大气压),"psi"(每平方英寸上受到的磅力压力),"Torr"(毫米汞柱);
9.能量单位:"J"(焦耳),"kJ"(千焦),"MJ"(兆焦),"kWh"(千瓦时),"cal"(卡路里),"kcal"(千卡),"BTU"(英热单位);
10.功率单位:"W"(瓦特),"kW"(千瓦),"MW"(兆瓦),"cal/s"(卡路里每秒),"BTU/h"(英热单位每小时),"hp"(马力);
11.温度单位:"0C"(摄氏度),"0F"(华氏度),"K"(开氏温标)。
用户也能够在MFP中获取一些物理或者化学常量值。函数get_constant(const_name, n)返回一个由区分大小写的字符串const_name所对应的常数值,返回的数值将会四舍五入后保留小数点后面n位有效数值,这里n为非负整数并且可以省略。如果n被省略,返回值将不会被四舍五入处理。本函数支持以下常数:
1.圆周率(const_name == "pi");
2.自然对数(const_name == "e");
3.真空中的光速[m/s](const_name == "light_speed_in_vacuum");
4.万有引力常数[m**3/kg/(s**2)](const_name == "gravitational_constant");
5.普朗克常数[J*s](const_name == "planck_constant");
6.磁常数(真空磁导率)[N/(A**2)](const_name == "magnetic_constant");
7.电常数(真空电容率)[F/m](const_name == "electric_constant");
8.基本电荷[c](const_name == "elementary_charge_constant");
9.阿伏伽德罗常数[1/mol](const_name == "avogadro_constant");
10.法拉第常数[C/mol](const_name == "faraday_constant");
11.气体常数[J/mol/K](const_name == "molar_gas_constant");
12.玻尔兹曼常量[J/K](const_name == "boltzman_constant");
13.标准重力[m/(s**2)](const_name == "standard_gravity");
举个例子,如果用户输入get_constant("pi", 4),结果将会是3.1416;如果用户输入get_constant("pi", 8),结果将会是3.14159265;如果用户输入get_constant("pi", 0),将会得到3,如果用户输入get_constant("pi")返回值将是3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 (小数点后有100位数字),这个数值就是本软件内部所使用的圆周率数值。
以下是上面这两个函数的例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test convert_unit and get_constant functions
@end
@language:simplified_chinese
测试convert_unit函数和get_constant函数
@end
endh
function getConstCvtUnit()
print("\nconvert_unit(23.71,\"m3\",\"fl oz(US)\") = " _
+ convert_unit(23.71,"m3","fl oz(US)"))
print("\nget_constant(\"pi\", 4) = " + get_constant("pi", 4))
print("\nget_constant(\"pi\", 8) = " + get_constant("pi", 8))
print("\nget_constant(\"pi\", 0) = " + get_constant("pi", 0))
print("\nget_constant(\"pi\") = " + get_constant("pi"))
endf
上述例子的运行结果如下:
convert_unit(23.71,"m3","fl oz(US)") = 801730.4782606974628681506740932151121554177525643799285007984748218874
get_constant("pi", 4) = 3.1416
get_constant("pi", 8) = 3.14159265
get_constant("pi", 0) = 3
get_constant("pi") = 3.1415926535897932384626433832795028841971693993751058209749445923
第3节 三角函数双曲三角函数
MFP语言的双曲函数和双曲三角函数和数学上对这些函数的定义同名,用法也一样。唯一需要注意的是,对于三角函数(包括反三角函数),如果结尾没有字母d,则是基于弧度的计算,结尾有字母d,则是基于角度的计算,比如cos(pi/3)返回0.5,而asind(0.5)则等于30,表示30度。还要注意这些函数都支持复数计算,比如asind(8)返回90 - 158.63249757 * i。
MFP所有三角函数和反三角函数的列表如下:
函数名 |
函数帮助信息 |
acos |
acos(1) : acos(x)返回x的反余弦值,注意x可以为复数。 |
acosd |
acosd(1) : 函数acosd(x)为余弦函数的反函数,注意返回值为角度数。 |
asin |
asin(1) : asin(x)返回x的反正弦值,注意x可以为复数。 |
asind |
asind(1) : 函数asind(x)为正弦函数的反函数,注意返回值为角度数。 |
atan |
atan(1) : atan(x)返回x的反正切值,注意x可以为复数。 |
atand |
atand(1) : 函数atand(x)为正切函数的反函数,注意返回值为角度数。 |
cos |
cos(1) : cos(x)返回x的余弦值,注意x可以为复数。 |
cosd |
cosd(1) : 函数cosd(x)返回基于角度的x的余弦值。 |
sin |
sin(1) : sin(x)返回x的正弦值,注意x可以为复数。 |
sind |
sind(1) : 函数sind(x)返回基于角度x的正弦值。 |
tan |
tan(1) : tan(x)返回x的正切值,注意x可以为复数。 |
tand |
tand(1) : 函数tand(x)返回基于角度x的正切值。 |
MFP所有双曲三角函数的列表如下:
函数名 |
函数帮助信息 |
acosh |
acosh(1) : 函数acosh(x)为双曲余弦函数的反函数。 |
asinh |
asinh(1) : 函数asinh(x)为双曲正弦函数的反函数。 |
atanh |
atanh(1) : 函数atanh(x)为双曲正切函数的反函数。 |
cosh |
cosh(1) : 函数cosh(x)为双曲余弦函数。 |
sinh |
sinh(1) : 函数sinh(x)返回x的双曲正弦值。 |
tanh |
tanh(1) : 函数tanh(x)用于计算x的双曲正切值。 |
以下是上述函数的例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test trigononmetric and hyperbolic trigononmetric functions
@end
@language:simplified_chinese
测试三角函数和双曲三角函数
@end
Endh
function testTrigHTrig()
print("\ncos(pi/3) = " + cos(pi/3))
print("\ntand(45) = " + tand(45))
print("\nsin(1 + 2*i) = " + sin(1 + 2*i))
print("\nasind(0.5) = " + asind(0.5))
print("\nacos(8) = " + acos(8))
print("\nacosh(4.71 + 6.44i) = " + acosh(4.71 + 6.44i))
print("\nsinh(e) = " + sinh(e))
print("\natanh(e) = " + atanh(e))
endf
运行上述例子函数返回的结果是:
cos(pi/3) = 0.5
tand(45) = 1
sin(1 + 2*i) = 3.1657785132161682200525265356615738370974142362979081716694416027 + 1.959601041421606115476765045922954107994611047413801140191859959i
asind(0.5) = 30.000000000000003071288025528876242434085090019423660218589920376
acos(8) = -2.768659383313573751905778408399783074855804443359375i
acosh(4.71 + 6.44i) = 2.771116084398325796200879267416894435882568359375 + 0.94305685974139741301058847966487519443035125732421875i
sinh(e) = 7.544137102816974971286612117182812653481960296630859375
atanh(e) = 0.385968416452652396397837719632661901414394378662109375 + 1.5707963267948966192313216916397514420985846996875529104874722962i
。需要注意的是asind(0.5)的返回值应该是30(sin30度等于0.5),但是实际上的结果是30.000000000000003071288025528876242434085090019423660218589920376,这是由于asind是将参数先转换为复数在进行计算的,转换的过程会造成微量的计算误差。
第4节 指数,对数和次方函数
MFP支持一系列的指数,对数和次方函数,参见下表:
函数名 |
函数帮助信息 |
exp |
exp(1) : exp(x)返回自然对数e的x次方,x可以为实数或者虚数。 |
lg |
lg(1) : 函数lg(x)返回x的自然对数。 |
ln |
ln(1) : 函数ln(x)返回x的自然对数。 |
log |
log(1) : log(x)返回x的自然对数,注意x可以为复数。 |
log10 |
log10(1) : 函数log10(x)返回x以十为底的对数。 |
log2 |
log2(1) : 函数log2(x)返回x以2为底的对数。 |
loge |
loge(1) : 函数loge(x)返回x的自然对数。 |
pow |
pow(2) : pow(x,y)返回x的y次方,注意x和y可以为实数,可以为虚数。如果结果有多个值,返回第一个值。 pow(3) : pow(x,y,z)返回包含x的y次方的前z个值组成的一个向量,如果x的y次方只有少于z个值,返回所有值。注意y必须为实数,x可以为实数,可以为虚数,z必须为正整数。 |
sqrt |
sqrt(1) : 函数sqrt(x)返回实数x的平方根值。 |
这里需要注意几点:
第一, lg(x)、log(x)、ln(x)和loge(x)返回的都是x的自然对数,log2(x)返回x的以2为底的对数,log10(x)返回x以10为底的对数。这些求对数的函数的参数都可以为复数。至于以其他任何数为底的对数,可以由这些对数函数相除得到,比如求x以3为底的对数的计算公式为log(x)/log(3)。
第二, pow函数有两种用法,第一种是pow(x,y),它返回x的y次方,注意x和y可以为实数,可以为虚数。如果结果有多个值,返回复平面上幅角从0度开始逆时针旋转遇到的第一个值。这种用法等价于使用次方操作符,也就是x**y。比如pow(32, 0.2)也就是32 的1/5次方得到2,但是pow(-32, 0.2)却不会返回-2(虽然-2是它的一个根),而是返回1.61803399 + 1.1755705 * i
第二种是pow(x,y,z),它返回包含x的y次方的前z个值(在复平面上从幅角0度开始逆时针旋转遇到的前z个值)组成的一个向量,如果x的y次方只有少于z个值,返回所有值。注意y必须为实数,x可以为实数,可以为虚数,z必须为正整数。比如,如果想要返回-32 的1/5次方的所有根,可以调用pow(-32, 0.2, 5)得到一个包含5个元素的数组也就是[1.61803399 + 1.1755705 * i, -0.61803399 + 1.90211303 * i, -2, -0.61803399 - 1.90211303 * i, 1.61803399 - 1.1755705 * i]。
第三, sqrt(x)函数实际上和表达式x**0.5或者pow(x, 0.5)的效果完全一样,都是返回在复平面上从幅角0度开始逆时针旋转遇到的x的第一个平方根。比如sqrt(4) == 2,sqrt(-2) == 1.41421356 * i和sqrt(-2+3i) == 0.89597748 + 1.67414923 * i。
以下是上述函数例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test log, exp and pow and related functions
@end
@language:simplified_chinese
测试对数,指数和次方函数
@end
endh
function testLogExpPow()
print("\nlg(e) == " + lg(e))
print("\nlog(9, 3) == log(9)/log(3) == " + log(9)/log(3))
print("\nlog2(3 + 4i) == " + log2(3 + 4i))
print("\npow(32, 0.2) == " + pow(32, 0.2))
print("\npow(-32, 0.2) == " + pow(-32, 0.2))
print("\npow(-32, 0.2, 5) == " + pow(-32, 0.2, 5))
print("\nsqrt(4) == " + sqrt(4))
print("\nsqrt(-2) == " + sqrt(-2))
print("\nsqrt(-2+3i) == " + sqrt(-2+3i))
endf
上述函数的运行结果如下:
lg(e) == 1
log(9, 3) == log(9)/log(3) == 2
log2(3 + 4i) == 2.3219280948873622916712631553180615794157506196217129274315603707 + 1.337804212450976175615004492526409565791145361743891813677556325i
pow(32, 0.2) == 2
pow(-32, 0.2) == 1.6180339887498949025257388711906969547271728515625 + 1.175570504584946274206913585658185184001922607421875i
pow(-32, 0.2, 5) == [1.6180339887498949025257388711906969547271728515625 + 1.175570504584946274206913585658185184001922607421875i, -0.6180339887498946804811339461593888700008392333984375 + 1.90211303259030728440848179161548614501953125i, -2, -0.6180339887498951245703437962220050394535064697265625 - 1.9021130325903070623638768665841780602931976318359375i, 1.6180339887498946804811339461593888700008392333984375 - 1.17557050458494671829612343572080135345458984375i]
sqrt(4) == 2
sqrt(-2) == 1.4142135623730951454746218587388284504413604736328125i
sqrt(-2+3i) == 0.8959774761298379706375607865525069497958199765590683867889064147 + 1.6741492280355400682758136732173307274213575287387175311747860088i
第5节 矩阵相关函数
上一章中介绍了MFP对数组的相关操作函数,这里,必须指出数组的概念和数学上的矩阵的相关和不同的地方。
首先,数学上的矩阵就是MFP中的数组,所以,对数组的基本操作,包括创建,存取,修改函数,以及加减乘除转置等操作符,对数学上的矩阵都是适用的。
其次,数学上的矩阵式一种特殊的数组,它必须是二维的,并且,在大多数情况下是一个方阵。这里介绍的函数,适用于数学上的矩阵(除了一个例外,也就是dprod函数,它用于两个一维向量的点乘),对于其他的MFP的数组,并不适用。
以下是当前版本的MFP所支持的矩阵函数的列表:
函数名 |
函数帮助信息 |
adj |
adj(1) : 函数cofactor(x)返回2维方阵x的伴随矩阵。 |
cofactor |
cofactor(1) : 函数cofactor(x)返回2维方阵x的余因子矩阵。 |
det |
det(1) : det(x)计算2维方阵x的行列式值。 |
deter |
deter(1) : deter(x)计算2维方阵x的行列式值。 |
dprod |
dprod(2) : 函数dprod用于计算两个同等长度的一维向量 [x1, x2, ... xn]和[y1, y2, ... yn]的点乘值。 |
eig |
eig(1) : eig(A)计算2维方阵A的特征向量和特征值。这个函数返回一个包含两个成员的列表。第一个成员是特征向量矩阵,每一列是一个特征向量。第二个成 员是一个对角矩阵,每一个对角线元素是一个特征值。注意运算这个函数非常耗费内存和CPU资源,如果在手机上运行,矩阵A的尺寸最好不要超过6*6,如果 在电脑上运行,最好不要超过8*8,否则可能造成内存不足而程序崩溃或者运行很长时间而没有结果。 eig(2) : eig(A, B)计算2维方阵A相对于同样尺寸的方阵B的特征向量和特征值,也就是Av = lambda * Bv,在这里,。lambda是一个特征值,v是一个特征向量。第二个参数,B,可以省略,其缺省值为I矩阵。这个函数返回一个包含两个成员的列表。第一 个成员是特征向量矩阵,每一列是一个特征向量。第二个成员是一个对角矩阵,每一个对角线元素是一个特征值。注意运算这个函数非常耗费内存和CPU资源,如 果在手机上运行,矩阵A的尺寸最好不要超过6*6,如果在电脑上运行,最好不要超过8*8,否则可能造成内存不足而程序崩溃或者运行很长时间而没有结果。 |
get_eigen_values |
get_eigen_values(1) : get_eigen_values(A)计算2维方阵A的特征值。这个函数返回所有特征值,包括重复的特征值的列表。注意运算这个函数非常耗费内存 和CPU资源,如果在手机上运行,矩阵A的尺寸最好不要超过6*6,如果在电脑上运行,最好不要超过8*8,否则可能造成内存不足而程序崩溃或者运行很长 时间而没有结果。 get_eigen_values(2) : get_eigen_values(A, B)计算2维方阵A相对于同样尺寸的方阵B的特征值,也就是Av = lambda * Bv,在这里,。lambda是一个特征值,v是一个特征向量。第二个参数,B,可以省略,其缺省值为I矩阵。这个函数返回所有特征值,包括重复的特征值 的列表。注意运算这个函数非常耗费内存和CPU资源,如果在手机上运行,矩阵A的尺寸最好不要超过6*6,如果在电脑上运行,最好不要超过8*8,否则可 能造成内存不足而程序崩溃或者运行很长时间而没有结果。 |
invert |
invert(1) : invert(x)返回方块2维矩阵x的逆矩阵,注意x中的元素可以为复数。 |
left_recip |
left_recip(1) : left_recip(x)计算x的左除倒数,注意当前仅支持数值或二维矩阵。 |
rank |
rank(1) : rank(matrix)返回矩阵的秩。比如,rank([[1,2],[2,4]])将返回1。注意这里的矩阵不见得非要是方阵。 |
recip |
recip(1) : recip(x)计算x的倒数,注意当前仅支持数值或二维矩阵。 |
这里需要注意几点:
第一, 对于二维方阵来讲,recip、left_recip和invert实际上是同一个函数,都是求取方阵x(也就是这些函数的参数)的倒数,相当于计算表达式1/x。
第二, Det和deter是同一个函数的不同名字,换句话说,它们的使用方法和计算结果完全一样。
第三, 所有的上述函数都支持复数矩阵。
以下是上述函数的例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test matrix functions
@end
@language:simplified_chinese
测试矩阵相关函数
@end
endh
function testMatrix()
print("\ncofactor([[1,3,-4.81-0.66i],[-0.91i,5.774,3.81+2.03i],[0,-6,-7.66-3i]])=" _
+ cofactor([[1,3,-4.81-0.66i],[-0.91i, 5.774, 3.81+2.03i],[0, -6, -7.66-3i]]))
print("\nadj([[1,-7],[-4, 6]]) = " + adj([[1,-7],[-4, 6]]))
print("\ndet([[2.7-0.4i, 5.11i],[-1.49, -3.87+4.41i]]) = " _
+ det([[2.7-0.4i, 5.11i],[-1.49, -3.87+4.41i]]))
print("\ndprod([1,2,3],[4,5,6]) = " + dprod([1,2,3],[4,5,6]))
print("\neig([[1,0],[0,1]]) = " + eig([[1,0],[0,1]]) )
print("\neig([[1+3.7i,-0.41-2.93i,5.33+0.52i],[0.33+2.71i,-3.81i,0.41+3.37i],[2.88,0,-9.4i]])=" _
+ eig([[1+3.7i,-0.41-2.93i,5.33+0.52i],[0.33+2.71i,-3.81i,0.41+3.37i],[2.88,0,-9.4i]]))
print("\nget_eigen_values([[1+3.7i,-0.41-2.93i,5.33+0.52i],[0.33+2.71i,-3.81i,0.41+3.37i],[2.88,0,-9.4i]])=" _
+get_eigen_values([[1+3.7i,-0.41-2.93i,5.33+0.52i],[0.33+2.71i,-3.81i,0.41+3.37i],[2.88,0,-9.4i]]))
print("\nrank([[1,2,3],[4,5,8]]) = " _
+ rank([[1,2,3],[4,5,8]]))
Endf
程序的运行结果如下:
cofactor([[1,3,-4.81-0.66i],[-0.91i,5.774,3.81+2.03i],[0,-6,-7.66-3i]])=[[-21.3688399999999999999999999999999999999999999999999999999999999986 - 5.1419999999999999999999999999999999999999999999999999999999999994i, 2.73 - 6.9706i, 5.46i], [51.84 + 12.96i, -7.66 - 3i, 6], [39.2029399999999999999999999999999999999999999999999999999999999999 + 9.9008400000000000000000000000000000000000000000000000000000000001i, -4.4106 + 2.3471i, 5.774 + 2.73i]]
adj([[1,-7],[-4, 6]]) = [[6, 7], [4, 1]]
det([[2.7-0.4i, 5.11i],[-1.49, -3.87+4.41i]]) = -8.685 + 21.0689i
dprod([1,2,3],[4,5,6]) = 32
eig([[1,0],[0,1]]) = [[[0, 0], [0, 0]], [[1, 0], [0, 1]]]
eig([[1+3.7i,-0.41-2.93i,5.33+0.52i],[0.33+2.71i,-3.81i,0.41+3.37i],[2.88,0,-9.4i]])=[[[0.5823305472444549220819340004695808799844908575313355771049880239 + 2.6809072575482156074378495725434812981406213152515868875585567468i, 0.0114135820466395502054852954488256551817471139007810529210119208 + 3.4394330048873032459793824252367034270060295989773214887206842872i, 0.1388649308606510232042228769561980233759262865380815606646575143 - 0.6869355577206501991055143100875158982393429000524385229074545558i], [0.1706650271410734493686782716838420204556348720948784459123114335 + 3.2610379517684265529500566832795301074088302158506118107692861942i, 1.0352846399044520080844175395063017457192992181908246617872107954 + 2.0718315370680215726468326567580658394348957576054643511780204727i, 1], [1, 1, -1.4604755542403403454627560718567442382313962988887573353544007743 + 0.5989937399782723545797394498168180189451427644426167079112280372i]], [[1.6771119760640303234132562527571544811705507223533275701869437736 - 1.6789870982611406187191411771858177830523877216751181685694659201i, 0, 0], [0, 0.0328711162943186887885582860890803241425541594114635568073761979 + 0.5055670540754347904151221100125363969735197371948964385418564962i, 0], [0, 0, -0.7099830923583490122018145388462348053131048817647911269943199715 - 8.3365799558142941716959809328267186139211320155197782699723905761i]]]
get_eigen_values([[1+3.7i,-0.41-2.93i,5.33+0.52i],[0.33+2.71i,-3.81i,0.41+3.37i],[2.88,0,-9.4i]])=[1.6771119760640303234132562527571544811705507223533275701869437736 - 1.6789870982611406187191411771858177830523877216751181685694659201i, 0.0328711162943186887885582860890803241425541594114635568073761979 + 0.5055670540754347904151221100125363969735197371948964385418564962i, -0.7099830923583490122018145388462348053131048817647911269943199715 - 8.3365799558142941716959809328267186139211320155197782699723905761i]
rank([[1,2,3],[4,5,8]]) = 2
第6节 表达式和微积分函数
将表达式和微积分函数放在一起,是因为这些函数都是对一个基于字符串的MFP表达式进行处理,函数的列表如下:
函数名 |
函数帮助信息 |
deri_ridders |
deri_ridders(4) : deri_ridders(expr, var, val, ord)返回基于变量var的表达式expr在var等于val的时候的ord阶导数值。这个函数使用Ridders法进行计算。比如,deri_ridders("x**2+x","x",3,2)返回2。 |
derivative |
derivative(2) : derivative(expression, variable)返回基于变量variable的表达式expression的导数表达式。注意expression和variable均为字符串。比如,derivative("x**2+x","x")返回一个字符串表达式"2*x+1"。 derivative(4) : derivative(expr, var, val, method)返回基于变量var的表达式expr在var等于val的时候的导数值。参数method用于选择计算方法,如果是true,意味着使用Ridders法进行计算,如果是false,则只是简单地计算导数表达式在val时候的值。比如,derivative("x**2+x","x",2,true)返回5。 |
evaluate |
evaluate(1...) : evaluate(expr_string,var_string1,var_value1,var_string2,var_value2, ...) 返回当基于字符串的变量var_string1等于var_value1,var_string2等于var_value2,...时,基于字符串的表达 式expr_string的值。注意变量var_string1,var_string2,...的值可以为任意类型。变量的数目可以为0,也就是 说,evaluate("3+2")是合法的。 |
integrate |
integrate(2) : integrate(x,y)返回基于变量y的表达式x的不定积分,表达式x和变量y均为字符串。注意如果表达式x不存在不定积分,或者x过于复杂无法解出其不定积分,本函数将会抛出异常。 integrate(4) : integrate(x,y,z,w)返回表达式x在变量y从z到w的积分值。表达式x和变量y均为字符串,z和w可以为实数,复数或字符串。注意本函数采用的积分算法是自适应Gauss-Kronrod积分法。 integrate(5) : integrate(x,y,z,w,v)返回表达式x相对于变量y从w到z的积分。计算时每一步步长为(w-z)/v。表达式x和变量y均为字符串,z 和w可以为实数,复数或字符串,v必须为正整数。注意如果v是0,则相当于执行integrate(x,y,z,w)。 |
product_over |
product_over(3) : 函数product_over(x, y, z)计算基于字符串的表达式x中的变量取值从整数y逐步变化到整数z的值的乘积。y和z必须是字符串的形式,其中,y必须写成一个赋值表达式,比 如"a=10",这里,a是变量名。一个函数的例子为product_over("x+1", "x=1", "10")。 |
sum_over |
sum_over(3) : 函数sum_over(x, y, z)计算基于字符串的表达式x中的变量取值从整数y逐步变化到整数z的值的总合。y和z必须是字符串的形式,其中,y必须写成一个赋值表达式,比 如"a=10",这里,a是变量名。一个函数的例子为sum_over("x+1", "x=1", "10")。 |
这些函数中,deri_ridders是使用Ridders法对一个函数求某一点的一阶,二阶或者三阶导数值。在列表中的例子deri_ridders("x**2+x", "x", 3, 2)表示求表达式x**2+x在x等于3时的二阶导数值。
derivative用于求取一个函数的一阶导数的表达式或者一阶导数在某一点的值。列表中的第一个例子derivative("x**2+x","x")表示求表达式x**2+x的一阶导数表达式,列表中的第二个例子derivative("x**2+x","x",2,true)表示求表达式x**2+x在x等于2时的一阶导数的值。需要注意的是最后一个参数true表示使用Ridders法求导数值,false表示直接将x的值代入导数表达式中求值。如果不给出最后一个参数,其缺省值为true。
derivative也可以用于求取函数的高阶导数表达式。这需要对derivative函数进行连环调用,比如derivative(derivative("x**2+x","x"),"x")给出表达式x**2+x的二阶导数表达式。
sum_over相当于数学中的求和符号∑,它的使用方法也和∑完全一样。比如,列表中的例子sum_over("x+1", "x=1", "10"),表示对表达式x+1求和,x的变化范围是从整数1变化到整数10,相当于数学表达式∑x=110(x+1)。
类似sum_over,product_over相当于数学中的求积符号∏,它的使用方法也和∏完全一样,比如列表中的例子product_over("x+1", "x=1", "10"),表示对表达式x+1求积,x的变化范围是从整数1变化到整数10,相当于数学表达式∏x=110(x+1)。
Evaluate函数是将一个字符串视为MFP表达式,然后求取该表达式的值。注意如果该表达式中有一个或多个未知变量,evaluate函数可以增加参数给未知变量赋值,以便最后求得结果,比如evaluate("x+y+1","x",3,"y",4)用于计算x+y+1的值,并且给出了x的值为3,y的值为4,所以最后的计算结果为8。当然,如果没有未知变量,就不必增加用于赋值的参数了。
Evaluate计算的MFP表达式还可以包括函数,无论是系统自带的函数还是用户定义的函数,比如evaluate("sind(30)")得到值为0.5。
Integrate函数则用于计算定积分或者不定积分。事实上,可编程科学计算器的计算积分的组件就是调用的这个函数。如果用这个函数计算不定积分比较简单,需要两个参数,第一个是被积分表达式,第二个是被积分变量,它们都是基于字符串的,比如
integrate("cos(x)","x")
就是对cos(x)积分,得到的不定积分结果表达式也是一个字符串,也就是"sin(x)"。
如果用于计算定积分,也有两种用法,第一种是采用高斯克朗德(Gauss-Kronrod)法,采用这种积分办法,能够处理起始和终止积分点为无穷的情况,也能够处理高频震荡函数,甚至能够处理某些奇异点的情况。代价就是计算速度比较慢。比如
integrate("exp(x)","x",-inf,0)
返回exp(x)从负无穷到0的积分(结果为1),而
integrate("log(x)","x",0,1)
返回log(x)从0到1的积分,注意这里0是奇异点,返回的结果为-1.00000018,注意这里有计算误差。
对于大部分函数,如果没有奇异点,也不是高频震荡,积分范围也不包括无穷大,则可以使用普通的梯形求和积分法。这时,用户需要指定积分步数,如果积分步数为0,或者积分范围包括无穷大,integrate又自动回到了采用高斯克朗德法进行积分。一个普通的梯形求和积分法的例子为:
integrate("x**2+1","x", -3+4i, 7-9i, 100)
,这个例子中,积分的起止点位于复数域(integrate支持复数域上积分),积分步数为100步,最后的结果为-481.7345 - 225.69505 * i,理论的结果为-481.66666667 - 225.66666667 * i。可见,对于诸如x**2+1之类的线性或者接近线形的函数,只要步数足够大,误差会很小。
通过嵌套integrate函数还可以实现高次积分,比如计算x*y的积分,x从1到6,y从-4到3,计算表达式为:
integrate("integrate(\"x*y\",\"x\",1,6,100)","y",-4,3,100)
,结果为-61.25。需要注意,由于高斯克朗德法速度比较慢,高次积分强烈不建议采用该积分法,这也是为什么在上述表达式中指定积分步骤的原因。
当然,也有可能,integrate函数无法得到积分结果(比如,有些不定积分过于复杂或者不可积,或者有些定积分无法收敛),这时,integrate函数会抛出异常,比如在命令提示符中运行下述语句块(直接将下述语句块拷贝粘贴到基于JAVA的可编程科学计算器的命令提示符中,按回车键即可运行):
try
print("integrate(\"e**(x**2)\",\"x\")", integrate("e**(x**2)","x"))
catch
print("e**(x**2) cannot be integrated")
endtry
用户可以看到integrate函数抛出异常,最后的结果为打印提示
e**(x**2) cannot be integrated
也就是e的x平方次方不可积。
最后要注意,以上介绍的所有表达式和积分函数,都能够读取已定义的变量的值,比如,在某个程序中已经声明了一个变量b,它的值为3,那么用户调用evaluate("x+b","x",9),就会返回12。由于这个原因,用户在使用上述函数的时候,最好能够保证函数内部定义的变量和程序中的变量的名字不同,免得发生冲突。这个在进行高次积分的时候特别要注意。
以下是上述函数的例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test expression and calculus functions
@end
@language:simplified_chinese
测试表达式和微积分相关函数
@end
endh
function exprcalculus()
print("\nderivative(\"1/x**2*log(x) + 9\", \"x\") = " _
+ derivative("1/x**2*log(x) + 9", "x"))
print("\nderivative(\"tanh(x)**-1\", \"x\") = " _
+ derivative("tanh(x)**-1", "x"))
// test high order derivative
// 测试高次导数
print("\nderivative(derivative(\"x*sin(x)\", \"x\"), \"x\") = " _
+ derivative(derivative("x*sin(x)", "x"), "x"))
// test derivative value
// 测试求取导数值
print("\nderi_ridders(\"x**0.5+x+9\", \"x\", 0.3, 1) = " _
+ deri_ridders("x**0.5+x+9", "x", 0.3, 1))
print("\nderivative(\"x**0.5+x+9\", \"x\", 0.3) = " _
+ derivative("x**0.5+x+9", "x", 0.3))
print("\nderi_ridders(\"x**0.5+sqrt(sin(x**2))\", \"x\", 0.3, 3) = " _
+ deri_ridders("x**0.5+sqrt(sin(x**2))", "x", 0.3, 3))
print("\nsum_over(\"1/(x-10)\",\"x=1\",\"9\") = " _
+ sum_over("1/(x - 10)", "x = 1", "9"))
print("\nproduct_over(\"1/(x-10)\",\"x=9\",\"1\") = " _
+ product_over("1/(x-10)", "x = 9", "1"))
print("\nevaluate(\"x+y+1\",\"x\",5,\"y\",7) = " _
+ evaluate("x+y+1","x",5,"y",7))
print("\nevaluate(\"sind(30)\") = " + evaluate("sind(30)"))
print("\nintegrate(\"tanh(x)**-1\",\"x\") = ")
print(integrate("tanh(x)**-1","x"))
print("\nintegrate(\"sinh(x)*cosh(x)**-1\",\"x\") = ")
print(integrate("sinh(x)*cosh(x)**-1","x"))
print("\nintegrate(\"1/x**2\",\"x\",2,inf) = ")
print(integrate("1/x**2","x",2,inf))
print("\nintegrate(\"1/x**2\",\"x\",2,50,100) = ")
print(integrate("1/x**2","x",2,50,100))
// test unintegratable.
// 测试不可积分
try
print("integrate(\"e**(x**2)\",\"x\")", integrate("e**(x**2)","x"))
catch
print("e**(x**2) cannot be integrated")
endtry
// test high order integration
// 测试高次积分
print("\nintegrate(\"integrate(\\\"x*y\\\",\\\"x\\\",1,6,100)\",\"y\",-4,3,100) = ")
print(integrate("integrate(\"x*y\",\"x\",1,6,100)","y",-4,3,100))
endf
上述例子的运行结果如下:
derivative("1/x**2*log(x) + 9", "x") = (-2)*log(x)*x**(-3)+x**(-3)
derivative("tanh(x)**-1", "x") = -(-0.5)*2.7182818284590452353602874713526624977572470936999595749669676277**x*(sinh(x)/cosh(x))**(-2)*sinh(x)*cosh(x)**(-2)+(-0.5)*2.7182818284590452353602874713526624977572470936999595749669676277**(-x)*(sinh(x)/cosh(x))**(-2)*sinh(x)*cosh(x)**(-2)+(-0.5)*2.7182818284590452353602874713526624977572470936999595749669676277**x*(sinh(x)/cosh(x))**(-2)/cosh(x)+(-0.5)*2.7182818284590452353602874713526624977572470936999595749669676277**(-x)*(sinh(x)/cosh(x))**(-2)/cosh(x)
derivative(derivative("x*sin(x)", "x"), "x") = (-1)*x*sin(x)+2*cos(x)
deri_ridders("x**0.5+x+9", "x", 0.3, 1) = 1.9128709291772078606011099231055019184972226816921057762830380748
derivative("x**0.5+x+9", "x", 0.3) = 1.91287092917527690172363463716465048491954803466796875
deri_ridders("x**0.5+sqrt(sin(x**2))", "x", 0.3, 3) = 7.1575232288636571107632429280365926329437264758531027037489228909
sum_over("1/(x-10)","x=1","9") = -2.828968253968253968253968253968253968253968253968253968253968254
product_over("1/(x-10)","x=9","1") = -0.0000027557319223985890652557319223985890652557319223985890652557
evaluate("x+y+1","x",5,"y",7) = 13
evaluate("sind(30)") = 0.5
integrate("tanh(x)**-1","x") = log(sinh(x))
integrate("sinh(x)*cosh(x)**-1","x") = log(cosh(x))
integrate("1/x**2","x",2,inf) = 0.4999999999999999800759152415811779636542182411236778807349767932
integrate("1/x**2","x",2,50,100) = 0.4847465087006575124658317917505673256758819785394978030710821748e**(x**2) cannot be integrated
integrate("integrate(\"x*y\",\"x\",1,6,100)","y",-4,3,100) = -61.25
注意,从1.7版的可编程科学计算器开始,引用空间的概念被加入,所以,在算微分和积分表达式时,给出的答案包括每个函数完整的引用路径。例如在旧版本中的log(x)在1.7版中为::mfp::math::log_exp::log(x)。这让答案显得有些冗长并且难于阅读。1.7.1版改进了这个问题,在算微分和积分表达式时,给出的答案仅仅包括函数的最短引用路径。如果该函数在缺省引用空间内并且没有同名函数,则仅仅给出不包括引用路径的函数名。
第7节 统计、随机和排序函数
可编程科学计算器提供了用统计和随机过程以及排序的函数。这些函数和数学上的表示方法基本相同,用户可以很方便地使用:
函数名 |
函数帮助信息 |
avg |
avg(0...) : 函数avg(…)返回任意个数参数的平均值。 |
beta |
beta(2) : 函数beta(z1, z2)返回复数z1和z2的beta函数值。注意z1和z2的实部必须是正数。 |
gamma |
gamma(1) : 函数gamma(z)返回复数z的gamma函数值。注意z的实部必须是正数。 |
gavg |
gavg(0...) : 函数gavg(…)返回任意个数参数的几何平均数值。 |
havg |
havg(0...) : 函数havg(…)返回任意个数参数的调和平均数值。 |
max |
max(0...) : 函数max(...)返回任意数目参数中的最大值。 |
med |
med(0...) : 函数med(…)返回任意数目参数的中位数。如果参数的个数为偶数个,返回中间两个参数的平均值。 |
min |
min(0...) : 函数min(...)返回任意数目参数中的最小值。 |
quick_sort |
quick_sort(2) : 函数quick_sort(desc, original_list)将拥有至少一个元素的向量original_list用快速排序法进行排序并返回排序后的向量。如果desc是true或者1,按照从大到小 排序,否则(false或者0)按照从小到大排序。比如,输入quick_sort(1, [5,6,7,9,4])得到[9,7,6,5,4]而输入quick_sort(0, [5,6,7,9,4])的结果是[4,5,6,7,9]。 |
ncr |
ncr(2) : 函数nCr(x, y)计算有x个元素的集合S的k个元素组合的个数。注意x,y都是非负整数,x >= y。 |
npr |
npr(2) : 函数nPr(x, y)计算有x个元素的集合S的k个元素排列的个数。注意x,y都是非负整数,x >= y。 |
rand |
rand(0) : rand()函数返回一个大于等于0小于1的随机浮点数。 |
stdev |
stdev(0...) : 函数stdev(…)返回任意个数参数的标准差,注意这些参数是一个大的集合中的采样。 |
stdevp |
stdevp(0...) : 函数stdevp(…)返回任意个数参数的标准差。 |
sum |
sum(0...) : 函数sum(…)返回任意个数参数的总合。 |
这里需要注意stdev函数和stdevp函数的区别。假设这两个函数的参数都是同样的实数序列x1,x2,x3,…,xN,那么stdev返回的是
而stdevp返回的是
这里,u是x1,x2,x3,…,xN的平均值。
以下是上述函数的例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test statistics and sorting functions
@end
@language:simplified_chinese
测试统计、随机和排序相关函数
@end
endh
function testStatSort()
print("\navg(1,5,9,-6,3,-18,7) = " + avg(1,5,9,-6,3,-18,7))
print("\nbeta(3.71, 23.55) = " + beta(3.71, 23.55))
print("\ngamma(5.44 - 10.31i) = " + gamma(5.44 - 10.31i))
print("\ngavg(1,5,9,-6,3,-18,7) = " + gavg(1,5,9,-6,3,-18,7))
print("\nhavg(1,5,9,-6,3,-18,7) = " + havg(1,5,9,-6,3,-18,7))
print("\nmax(1,5,9,-6,3,-18,7) = " + max(1,5,9,-6,3,-18,7))
print("\nmed(1,5,9,-6,3,-18,7) = " + med(1,5,9,-6,3,-18,7))
print("\nmin(1,5,9,-6,3,-18,7) = " + min(1,5,9,-6,3,-18,7))
print("\nquick_sort(1,[1,5,9,-6,3,-18,7]) = " _
+ quick_sort(1,[1,5,9,-6,3,-18,7]))
print("\nquick_sort(0,[1,5,9,-6,3,-18,7]) = " _
+ quick_sort(0,[1,5,9,-6,3,-18,7]))
print("\nstdev(1,5,9,-6,3,-18,7) = " + stdev(1,5,9,-6,3,-18,7))
print("\nstdevp(1,5,9,-6,3,-18,7) = " + stdevp(1,5,9,-6,3,-18,7))
print("\nsum(1,5,9,-6,3,-18,7) = " + sum(1,5,9,-6,3,-18,7))
print("\nncr(8,3) = " + ncr(8,3))
print("\nnpr(8,3) = " + npr(8,3))
print("\nrand() = " + rand())
endf
上述例子程序运行结果如下:
avg(1,5,9,-6,3,-18,7) = 0.1428571428571428571428571428571428571428571428571428571428571429
beta(3.71, 23.55) = 0.0000279537392314725872716390423881975646941670888511331711318296
gamma(5.44 - 10.31i) = 0.0015360621732035695620552936894943183717820318136617456390043119 - 0.0279816213196075726360710743099268272949427989554500480691282345i
gavg(1,5,9,-6,3,-18,7) = 5.194584255413065676521000568754971027374267578125
havg(1,5,9,-6,3,-18,7) = 4.472616632860040567951318458417849898580121703853955375253549696
max(1,5,9,-6,3,-18,7) = 9
med(1,5,9,-6,3,-18,7) = 3
min(1,5,9,-6,3,-18,7) = -18
quick_sort(1,[1,5,9,-6,3,-18,7]) = [9, 7, 5, 3, 1, -6, -18]
quick_sort(0,[1,5,9,-6,3,-18,7]) = [-18, -6, 1, 3, 5, 7, 9]
stdev(1,5,9,-6,3,-18,7) = 9.3528707077661721314143505878746509552001953125
stdevp(1,5,9,-6,3,-18,7) = 8.65907569182385117301237187348306179046630859375
sum(1,5,9,-6,3,-18,7) = 1
ncr(8,3) = 56
npr(8,3) = 336
rand() = 0.67638281271680666950629756684065796434879302978515625
第8节 信号处理函数
为了方便电子电气工程师,MFP提供了三个信号处理函数:conv(卷积),FFT(快速傅立叶变换)和iFFT(快速傅立叶变换的逆变换),用法和示例如下:
函数名 |
函数帮助信息 |
conv |
conv(2) : conv(input_a, inputb)返回input_a和input_b的卷积。Input_a和input_b要么都是一维向量,要么都是二维矩阵。当前本函数仅仅支持一维和二维卷积,比如: conv([4,8,2,9],[5,3,8,9,6,7,8]) = [20, 52, 66, 151, 139, 166, 181, 132, 79, 72] conv([[4,8,2,9],[8,6,7,9],[2,2,8,-4]],[[-5,i,7],[0.6,8,4]]) = [[-20, -40 + 4 * i, 18 + 8 * i, 11 + 2 * i, 14 + 9 * i, 63], [-37.6, 6.8 + 8 * i, 102.2 + 6 * i, 50.4 + 7 * i, 129 + 9 * i, 99], [-5.2, 57.6 + 2 * i, 58.2 + 2 * i, 119.4 + 8 * i, 156 - 4 * i, 8], [1.2, 17.2, 28.8, 69.6, 0, -16]] |
FFT |
FFT(1...) : FFT(a, ...)返回对一个数值向量作快速傅立叶变换后的值。注意数值向量中数值的个数必须是2的整数次方。如果参数a是一个数值序列,则本函数只可能拥有一个参 数,返回值为对序列a[0], a[1], ..., a[N-1]作快速傅立叶变换的返回值。如果参数a仅仅是一个实数或者虚数,则本函数最少包含2个参数,而返回序列a, optional_params[0], ..., optional_params[number_of_optional_params - 2], optional_params[number_of_optional_params - 1]快速傅立叶变换后的值。注意返回值总是一个数组。 函数例子: FFT(1, 2, 3, 4)返回[10, -2+2i, -2, -2 - 2i]; FFT([1, 2, 3, 4])同样也是返回[10, -2+2i, -2, -2 - 2i]; |
IFFT |
IFFT(1...) : IFFT(a, ...)返回对一个数值向量作快速傅立叶变换的逆变换后的值。注意数值向量中数值的个数必须是2的整数次方。如果参数a是一个数值序列,则本函数只可能拥 有一个参数,返回值为对序列a[0], a[1], ..., a[N-1]作快速傅立叶变换德逆变换的返回值。如果参数a仅仅是一个实数或者虚数,则本函数最少包含2个参数,而返回序列a, optional_params[0], ..., optional_params[number_of_optional_params - 2], optional_params[number_of_optional_params - 1]快速傅立叶变换的逆变换后的值。注意返回值总是一个数组。 函数例子: IFFT(10, -2 + 2i, -2, -2 - 2i)返回[1, 2, 3, 4]; IFFT([10, -2 + 2i, -2, -2 - 2i])同样也是返回[1, 2, 3, 4]; |
以下是上述函数的例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test sign processing functions
@end
@language:simplified_chinese
测试信号处理相关函数
@end
endh
function testSignalProc()
print("\nconv([4,8,2,9],[5,3,8,9,6,7,8]) = " _
+ conv([4,8,2,9],[5,3,8,9,6,7,8]))
print("\nconv([[4,8,2,9],[8,6,7,9],[2,2,8,-4]],[[-5,i,7],[0.6,8,4]]) = " _
+ conv([[4,8,2,9],[8,6,7,9],[2,2,8,-4]],[[-5,i,7],[0.6,8,4]]))
print("\nFFT(1, 2, 3, 4) = " + FFT(1, 2, 3, 4))
print("\nFFT([1,2,3,4]) = " + FFT([1,2,3,4]))
print("\niFFT(10, -2 + 2i, -2, -2 - 2i) = " _
+ IFFT(10, -2 + 2i, -2, -2 - 2i))
print("\niFFT([10, -2 + 2i, -2, -2 - 2i]) = " _
+ IFFT([10, -2 + 2i, -2, -2 - 2i]))
Endf
上述例子的运行结果如下:
conv([4,8,2,9],[5,3,8,9,6,7,8]) = [20, 52, 66, 151, 139, 166, 181, 132, 79, 72]
conv([[4,8,2,9],[8,6,7,9],[2,2,8,-4]],[[-5,i,7],[0.6,8,4]]) = [[-20, -40 + 4i, 18 + 8i, 11 + 2i, 14 + 9i, 63], [-37.6, 6.8 + 8i, 102.2 + 6i, 50.4 + 7i, 129 + 9i, 99], [-5.2, 57.6 + 2i, 58.2 + 2i, 119.4 + 8i, 156 - 4i, 8], [1.2, 17.2, 28.8, 69.6, 0, -16]]
FFT(1, 2, 3, 4) = [10, -2 + 2i, -2, -2 - 2i]
FFT([1,2,3,4]) = [10, -2 + 2i, -2, -2 - 2i]
iFFT(10, -2 + 2i, -2, -2 - 2i) = [1, 2, 3, 4]
iFFT([10, -2 + 2i, -2, -2 - 2i]) = [1, 2, 3, 4]
第9节 阶乘求值函数、判断质数函数和多项式求根函数
MFP中求取一个非负整数的阶乘的函数为factor,比如factor(3)得到6。注意这个函数只有一个参数,如果该参数不是整数,将会被先截断转换为整数在进行计算,如果参数的值小于0或者不能被转换为整数,将会出错。
MFP判断一个数是否为质数的函数式为is_prime,比如is_prime(3.3)得到false而is_prime(97)得到true。注意这个函数只有一个参数,并且该参数必须为实数,如果参数不是实数,将会报错。
MFP一元多项式求根的函数为roots。roots(a, ...)返回一个多项式的根数列。如果a是一个包含N个元素的实数或虚数数列,则返回多项式
a[0] * x**(N-1) + a[1] * x**(N-2) + ... + a[N-2] * x + a[N-1] == 0
的根数列。如果a是一个单一的实数,此函数则必须拥有至少两个参数,返回多项式
a * x**(除a之外其它参数的个数) + 除a之外的第一个参数 * x**(除a之外其它参数的个数 - 1) + … +除a之外的倒数第二个参数 * x +除a之外的最后一个参数 == 0
的根数列。
需要注意的是,如果该多项式次数大于等于4,根的计算是通过牛顿拉夫逊法给出的近似值。由于牛顿拉夫逊法需要迭代计算,运算时间会比较长(取决于设备的性能)。
例如,如果要计算多项式3 * x**2 - 4 * x + 1 == 0的根,在命令提示符中输入命令:roots([3, -4, 1])获得的结果是[1, 0.33333333];
如果要计算多项式(1+2i) * x**3 + (7-6i) * x**2 + 0.54 * x - 4.31 - 9i == 0的根,输入命令:roots(1+2i, 7-6i, 0.54, -4.31-9i)获得的结果是[0.79288607 + 3.9247084 * i, -0.56361748 - 0.78399569 * i, 0.7707314 + 0.85928729 * i]。
roots函数和用solve程序块求解一元多项式得出的结果是一样的,但是由于roots语句不必对程序块的语法结构进行分析,它比用solve程序块的效率要高。
以下是上述函数的例子程序。本例子可以在本手册自带的示例代码所在目录中的math libs子目录中的examples.mfps文件中找到):
Help
@language:
test prime, factor and roots functions
@end
@language:simplified_chinese
测试质数、阶乘和一元多项式求根的相关函数
@end
endh
function PrimeFactRoots()
print("\nis_prime(3.3) = " + is_prime(3.3))
print("\nis_prime(97) = " + is_prime(97))
print("\nis_prime(-97) = " + is_prime(-97))
print("\nis_prime(1) = " + is_prime(1))
print("\nis_prime(2) = " + is_prime(2))
print("\nis_prime(0) = " + is_prime(0))
print("\nis_prime(8633) = " + is_prime(8633))
print("\nfact(3) = " + fact(3))
print("\nfact(63) = " + fact(63))
print("\nfact(0) = " + fact(0))
print("\nroots([3, -4, 1]) = " + roots([3, -4, 1]))
print("\nroots(1+2i, 7-6i, 0.54, -4.31-9i) = " _
+ roots(1+2i, 7-6i, 0.54, -4.31-9i))
Endf
上述例子的运行结果如下:
is_prime(3.3) = FALSE
is_prime(97) = TRUE
is_prime(-97) = FALSE
is_prime(1) = FALSE
is_prime(2) = TRUE
is_prime(0) = FALSE
is_prime(8633) = FALSE
fact(3) = 6
fact(63) = 1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000
fact(0) = 1
roots([3, -4, 1]) = [1, 0.3333333333333333333333333333333333333333333333333333333333333333]
roots(1+2i, 7-6i, 0.54, -4.31-9i) = [0.7928860730571022099839052581254713102006395451929364570881977409 + 3.9247083954445877597678511535081536006180195929229657166716945562i, -0.5636174763329694374664831861988500484145796260620965968434731734 - 0.7839956883798520996055087388165005568364007706209239481847346781i, 0.7707314032758672274825779280733787382139400808691601397552754324 + 0.8592872929352643398376575853083469562183811776979582315130401219i]
小结
MFP编程语言提供了完整的数学和科学的函数。这些函数符合它们在相关领域的使用方法,简单易学。
MFP编程语言还提供了用于表达式和微积分的函数,这些函数的共同特点是使用基于字符串的数学公式表达式作为参数。和后面将会提到的绘图函数不同的是,这些函数可以接受参数数学公式字符串中含有已经声明的变量。对于这种情况,这些函数将自动把已经声明的变量的数值代入表达式进行计算。