Есть ли способ обрезать формулу строки, взятую из объекта JSON, и применить ее с помощью переменных PHP? [Дубликат]

  выберите имя, max (значение) из группы out_pumptable по имени  
18
задан Langkiller 18 September 2013 в 20:33
поделиться

6 ответов

Хотя я не предлагаю использовать eval для этого (это not решение), проблема в том, что eval ожидает полные строки кода, а не только фрагменты.

$ma ="2+10";
$p = eval('return '.$ma.';');
print $p;

Должен делать то, что вы хотите.


Лучшим решением было бы написать токенизатор / парсер для вашего математического выражения. Вот простой пример, основанный на регулярном выражении, который дает вам пример:

$ma = "2+10";

if(preg_match('/(\d+)(?:\s*)([\+\-\*\/])(?:\s*)(\d+)/', $ma, $matches) !== FALSE){
    $operator = $matches[2];

    switch($operator){
        case '+':
            $p = $matches[1] + $matches[3];
            break;
        case '-':
            $p = $matches[1] - $matches[3];
            break;
        case '*':
            $p = $matches[1] * $matches[3];
            break;
        case '/':
            $p = $matches[1] / $matches[3];
            break;
    }

    echo $p;
}
37
ответ дан Rocket Hazmat 15 August 2018 в 17:03
поделиться
  • 1
    Я добавил предложение для лучшего решения. Это не самое большое, но я надеюсь, что это дает представление о том, что вам нужно делать. Я уверен, что вы можете использовать Google для лучшего решения. – Rocket Hazmat 18 September 2013 в 20:48
  • 2
    Это действительно хорошо, за исключением моей функции, когда у меня есть 24,5 * 12, она берет первый номер как 5 вместо 24,5, так как он смотрит исключительно на цифры – Warren Sergent 2 February 2016 в 22:43
  • 3
    Замена шаблона следующим образом сделала трюк для меня (позволяет цифры, пробелы и десятичные числа) - обратите внимание, что он будет соответствовать номерам с пробелами в них (т.е. «201.5 + 11 2012 = 212,5», поэтому математика не будет работать полностью (через str_replace вокруг $matches[1] и $matches[3] или аналогичного), это будет полностью зависеть от вашего использования - это сработало для моих нужд. /([\d\.\s]+)([\+\-\*\/])([\d\.\s]+)/ – Warren Sergent 3 February 2016 в 07:28
  • 4
    Еще один шаг: /([\d\.\s]+)([\+\-\*\/])(\-?[\d\.\s]+)/ позволит второму числу быть отрицательным значением (например, в случае 24,5 * -4). Это сломалось бы, так как вторая группа не нашла бы отрицательного числа. – Warren Sergent 3 February 2016 в 07:44
  • 5
    Как бы вы посоветовали заняться 100+01? Я использую функцию eval, но я немного смущен тем, как писать регулярное выражение для проверки чисел, таких как 011,090,001 etc etc – halapgos1 4 October 2016 в 20:44

Выражение eval'd должно заканчиваться на «;»

Попробуйте следующее:

$ma ="2+10;";
$p = eval($ma);
print $p;

Кстати, это выходит за рамки, но функция «eval» выиграла 't возвращает значение выражения. eval ('2 + 10') не вернется 12. Если вы хотите, чтобы он вернул 12, вы должны eval ('return 2 + 10;');

-2
ответ дан ibtarek 15 August 2018 в 17:03
поделиться
  • 1
    который покажет пустую страницу, поскольку переменная $p пуста. добавьте echo внутрь: $ma ="echo 2+10;"; – S.Thiongane 18 September 2013 в 20:45
  • 2
    @mansoulx. Именно это было сказано в ответе выше («return 2 + 10»). – ibtarek 19 September 2013 в 03:39

Взгляните на это.

Я использую это в системе учета, где вы можете писать математические выражения в полях ввода количества.

Примеры

$Cal = new Field_calculate();

$result = $Cal->calculate('5+7'); // 12
$result = $Cal->calculate('(5+9)*5'); // 70
$result = $Cal->calculate('(10.2+0.5*(2-0.4))*2+(2.1*4)'); // 30.4

Код

class Field_calculate {
    const PATTERN = '/(?:\-?\d+(?:\.?\d+)?[\+\-\*\/])+\-?\d+(?:\.?\d+)?/';

    const PARENTHESIS_DEPTH = 10;

    public function calculate($input){
        if(strpos($input, '+') != null || strpos($input, '-') != null || strpos($input, '/') != null || strpos($input, '*') != null){
            //  Remove white spaces and invalid math chars
            $input = str_replace(',', '.', $input);
            $input = preg_replace('[^0-9\.\+\-\*\/\(\)]', '', $input);

            //  Calculate each of the parenthesis from the top
            $i = 0;
            while(strpos($input, '(') || strpos($input, ')')){
                $input = preg_replace_callback('/\(([^\(\)]+)\)/', 'self::callback', $input);

                $i++;
                if($i > self::PARENTHESIS_DEPTH){
                    break;
                }
            }

            //  Calculate the result
            if(preg_match(self::PATTERN, $input, $match)){
                return $this->compute($match[0]);
            }
            // To handle the special case of expressions surrounded by global parenthesis like "(1+1)"
            if(is_numeric($input)){
                return $input;
            }

            return 0;
        }

        return $input;
    }

    private function compute($input){
        $compute = create_function('', 'return '.$input.';');

        return 0 + $compute();
    }

    private function callback($input){
        if(is_numeric($input[1])){
            return $input[1];
        }
        elseif(preg_match(self::PATTERN, $input[1], $match)){
            return $this->compute($match[0]);
        }

        return 0;
    }
}
28
ответ дан jptsetung 15 August 2018 в 17:03
поделиться
  • 1
    Ваш класс очень полезен! Спасибо! Но можете ли вы расширить свой класс, что & quot; (5 + 2) & quot; не возвращается 0? – Flo 21 October 2015 в 07:36
  • 2
    может ли он решить 13 / 18-1 / 2 x 40, 13/18 x 40, 14 3/16/21 x 40, 16 3/16/23 x 40, 16-3 / 16/30 x 60, 9,75 X 21,5 / 29,5, 1/4 x 5, 1/2 x 6, 7 x 60, 8 Ga. X 4, 22 x 36, 35/64 x 6 – Pushpendra Singh 1 July 2016 в 10:09
  • 3
    Я написал короткий тест для ваших выражений. @PushpendraSingh. Если он соответствует вашим требованиям (например, обнаруживает пробелы, верхний регистр x и т. Д.), Вам нужно. gist.github.com/DBX12/2e1d622a0fa0937874ac3cf5eeecef51 – DBX12 6 March 2017 в 14:02
  • 4
    Поскольку, create_function обесценивается в php 7.2, как бы была переписана функция compute ()? Я не хочу использовать eval, но эти швы работают: private function compute ($ input) {return 0 + eval ('return'. $ Input. ';');} – Brainware 25 April 2018 в 18:33
  • 5
    Добавить if (is_numeric ($ input)) {return $ input;} после if (preg_match (self :: PATTERN test, если вы хотите, чтобы он не возвращал 0 для таких выражений с глобальной скобкой "(1 + 1)" ( Я изменил код) – jptsetung 17 May 2018 в 17:48

Использование функции eval очень опасно, если вы не можете управлять строковым аргументом.

Попробуйте Matex для безопасного вычисления математических формул.

0
ответ дан Marcodor 15 August 2018 в 17:03
поделиться
  • 1
    Какой стандарт вы использовали для обозначения ваших переменных и методов с прописными буквами? Это не условно. Дружественный совет - измените общий стандарт, если вы хотите, чтобы другие люди использовали вашу библиотеку. – Alex Kalmikov 13 December 2017 в 11:59
  • 2
    @ AlexCalm1Kov, oki, постарается приспособиться к верблюду, но мне это не нравится. В настоящее время он совместим с PSR, поэтому должен работать с автопогрузчиками. – Marcodor 13 December 2017 в 12:23

Решено!

<?php 
function evalmath($equation)
{
    $result = 0;
    // sanitize imput
    $equation = preg_replace("/[^a-z0-9+\-.*\/()%]/","",$equation);
    // convert alphabet to $variabel 
    $equation = preg_replace("/([a-z])+/i", "\$$0", $equation); 
    // convert percentages to decimal
    $equation = preg_replace("/([+-])([0-9]{1})(%)/","*(1\$1.0\$2)",$equation);
    $equation = preg_replace("/([+-])([0-9]+)(%)/","*(1\$1.\$2)",$equation);
    $equation = preg_replace("/([0-9]{1})(%)/",".0\$1",$equation);
    $equation = preg_replace("/([0-9]+)(%)/",".\$1",$equation);
    if ( $equation != "" ){
        $result = @eval("return " . $equation . ";" );
    }
    if ($result == null) {
        throw new Exception("Unable to calculate equation");
    }
    echo $result;
   // return $equation;
}


$a = 2;
$b = 3;
$c = 5;
$f1 = "a*b+c";

$f1 = str_replace("a", $a, $f1);
$f1 = str_replace("b", $b, $f1);
$f1 = str_replace("c", $c, $f1);

evalmath($f1);
/*if ( $equation != "" ){

    $result = @eval("return " . $equation . ";" );
}
if ($result == null) {

    throw new Exception("Unable to calculate equation");
}
echo $result;*/
?>
0
ответ дан perror 15 August 2018 в 17:03
поделиться

eval Оценивает данный код как PHP. Это означает, что он выполнит данный параметр как часть кода PHP.

Чтобы исправить ваш код, используйте это:

$ma ="print (2+10);";
eval($ma);
0
ответ дан S.Thiongane 15 August 2018 в 17:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: