2009-11-02 25 views
2

我寫了一個極地功能的工具。它列出從輸入範圍那樣的值:如何從Perl中的用戶輸入解析數學函數?

 
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 +褐色($ 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])); } 
+0

到目前爲止你有什麼? – 2009-11-02 14:39:03

+1

一面評論:用chomp代替chop:更安全。 –

+0

難道你不應該有$ t = $ flRad而不是$ t = $ i嗎? –

回答

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"); 
} 
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中找出錯誤,請檢查[email protected]變量。

1

根據你還在做什麼,我想我會跳過解析的想法,並讓用戶創建一個Perl庫或子類。他們將代碼封裝在子程序名稱中,並告訴腳本庫和子名稱。您也可以將其與適當的配置文件或命令行選項結合使用。

+0

所以沒有辦法做到這一點? – maxedmelon

+0

Perl中沒有任何內容可以成爲數學解析器。如果這是你問題的癥結所在,那麼你使用的是錯誤的語言。有很多方法可以完成,包括我的建議。 –