如何从Perl中的用户输入解析数学函数?

时间:2009-11-02 14:35:07

标签: perl math

我为极地功能编写了一个工具。它列出了输入范围内的值:

0 Grad: (0 RAD|1 RES)  
20 Grad: (0.349065850398866 RAD|1.3639702342662 RES)  
40 Grad: (0.698131700797732 RAD|1.83909963117728 RES)  
60 Grad: (1.0471975511966 RAD|2.73205080756888 RES)  
80 Grad: (1.39626340159546 RAD|6.67128181961771 RES)  
100 Grad: (1.74532925199433 RAD|4.67128181961771 RES)  
120 Grad: (2.0943951023932 RAD|0.732050807568878 RES)  
140 Grad: (2.44346095279206 RAD|0.16090036882272 RES)  
160 Grad: (2.79252680319093 RAD|0.636029765733797 RES)  
180 Grad: (3.14159265358979 RAD|1 RES)

它基于功能

 abs(1 + tan($_[0]));

如何从UserInput(Perl语法)解析这样的函数并将其分配给变量?

我想避免更改Perl脚本;使函数动态而不是静态。

欢迎并感谢阅读。

编辑: 对不起quadrupelpost ....

感谢您的帮助,但以下代码段提供了错误的值:

print("Eingabe: Funktion (phi = $t); PERL syntax!: > ");
$iFunktion = <STDIN>;
chop($iFunktion);

print("Eingabe: Grad Start: > ");
$iGradStart = <STDIN>; 
chop($iGradStart);

print("Eingabe: Grad End: > ");
$iGradEnd = <STDIN>; 
chop($iGradEnd);

print("Eingabe: Schrittweite: > ");
$iSchrittweite = <STDIN>; 
chop($iSchrittweite);

print("\nBerechne Funktion von $iGradStart bis $iGradEnd Grad mit einer Schrittweite von $iSchrittweite\n");


for ($i = $iGradStart; $i < $iGradEnd; $i = $i + $iSchrittweite)
{
    $flRad = &deg2rad($i);
    #$flResult = &Compute($flRad);
    $t = $i;
    $flResult = eval($iFunktion);
    print("$i Grad: ($flRad RAD|$flResult RES)  \n");
}

输入为abs(1 + tan($ t));


(其他信息,后续合并)

print("Eingabe: Grad Start: > "); 
$iGradStart = <STDIN>; 
chop($iGradStart); 

print("Eingabe: Grad End: > "); 
$iGradEnd = <STDIN>; 
chop($iGradEnd); 

print("Eingabe: Schrittweite: > "); 
$iSchrittweite = <STDIN>; chop($iSchrittweite); 
print("\nfrom $iGradStart to $iGradEnd Grad with $iSchrittweite\n"); 
for ($i = $iGradStart; $i <= $iGradEnd; $i = $i + $iSchrittweite) 
{ 
  $flRad = &deg2rad($i); 
  $flResult = &Compute($flRad); 
  print("$i Grad: ($flRad RAD|$flResult RES) \n"); 
} 

sub Compute { return abs(1 + tan($_[0])); }

3 个答案:

答案 0 :(得分:4)

您应该查看eval statement。它允许您将字符串计算为Perl代码。

例如,此代码:

print "Function? ";
chomp($function = <STDIN>);

for ($i = 0;$i < 10;$i++) {
  print $i,"->",eval($function),"\n";
}

给出这个:

Function? $i * $i
0->0
1->1
2->4
3->9
4->16
5->25
6->36
7->49
8->64
9->81

当您将用户输入作为代码运行时,如果除了使用之外的其他人正在使用您的脚本,您将需要做一些事情来清理用户输入。您可能还想进行替换,以便用户可以输入x而不是$i等。如果您想从eval抓取错误,请检查$@变量

答案 1 :(得分:1)

根据你的其他内容,我想我会跳过解析的想法并让用户创建一个Perl库或子类。它们将代码包装在子例程名称中,并告诉脚本库和子名称。您也可以将它与适当的配置文件或命令行选项结合使用。

答案 2 :(得分:0)

Math::Expression::Evaluator 几乎做你想要的,除了没有abs()并且无法添加用户功能(回调)。我花了大约五分钟来添加一些初步的支持,思想。

#!/usr/bin/perl
use strict;
use warnings;
use Math::Trig;
use Math::Expression::Evaluator;

my $expr = join ' ', @ARGV;
die "No expression provided" unless $expr;
my $m = Math::Expression::Evaluator->new;
# NOT in the distribution
$m->add_user_function('abs', sub { abs($_[0]) });
my $func = $m->parse($expr);
die "Cannot parse" unless $func;
for my $i (0 .. 10){
    my $rads = deg2rad($i);
    my $res = $func->val({x => $_});
    print("$i Grad: ($rads RAD|$res RES)  \n");
}