Как я могу разобрать математическую функцию из пользовательского ввода в Perl? - PullRequest
2 голосов
/ 02 ноября 2009

Я написал инструмент для полярных функций. В нем перечислены значения из входного диапазона, например:

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; сделать функцию динамической, а не статической.

Привет и спасибо за чтение.

EDIT: простите за четвероногий пост ....

Спасибо за помощь, но следующий фрагмент дает неправильные значения:

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])); }

Ответы [ 3 ]

4 голосов
/ 02 ноября 2009

Вы должны взглянуть на оператор eval . Это позволяет вам оценивать строку как код 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 голос
/ 02 ноября 2009

В зависимости от того, что еще у вас происходит, я думаю, что я пропущу идею разбора и предложу пользователям создать Perl-библиотеку или подкласс. Они обертывают свой код в имена подпрограмм и сообщают вашему сценарию библиотеку и имя подпрограммы. Вы также можете комбинировать это с правильным файлом конфигурации или параметрами командной строки.

0 голосов
/ 02 ноября 2009

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");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...