ФорумПрограммированиеПыхнуть хотите?Готовые решения → Калькулятор

Калькулятор

  • vasa_c

    Сообщения: 3127 Репутация: N Группа: в ухо

    Spritz 12 октября 2007 г. 5:55

    [size=12]Классик для вычисления выражений[/size]

    Исходник — http://pyha.ru/forum/resh/calcul.php.
    Работает только в PHP5.

    Можно использовать для безопасных вычислений выражений, введенных пользователем и подобных задач.

    Вычисления производятся над числами, допустимые операторы — "+", "-", "*", "/", "%" (взятие остатка). Точность вычислений — до 4-го символа после запятой.

    Примеры:

    print calculator::calc('2+3').'<br />'; // 5
    print calculator::calc('(1 + 2 * 3 + 4 * (5 - (67 % 8))) / -4.3').'<br />'; // -3.4884



    Переменные

    Возможно использование переменных. Имена переменных регистрозависимые и могут состоять из латинских букв, цифр и знаков подчеркивания. Цифра не может быть первой.


    $context = Array('a' => 1, 'b' => 2, 'c' => 3);
    print calculator::calc('a + b * c / 4', $context).'<br />'; // 2,5


    Вторым параметром можно передать в функцию ассоциативный массив переменных, которые можно использовать в выражении. Либо, для более сложных случаев, объект, имеющий метод get(string), который возвращает переменную по имени. Для несуществующих переменных он должен возвращать null.

    Функции

    Так же допустимо использование функций. Имена функций могут иметь тот же формат, что и переменные. Имя функции может совпадать с именем переменной. Сразу после имени функции, без пробелов, должны идти скобки с аргументами, иначе идентификатор будет считаться переменной. Аргументы разделяются запятыми и могут быть любыми выражениями.


    $expression = 'max(a, b, 15) - sum(1, 2, max(3, 4 * 2) - 2/5, -7)';
    $functions = Array('sum' => 'fSum', 'max' => 'fMax');
    $context = Array('a' => 10, 'b' => 20);

    print calculator::calc($expression, $context, $functions).'<br />'; // 16.4

    /* Суммирование аргументов */
    function fSum() {
    return array_sum(func_get_args());
    }

    /* Максимальный аргумент */
    function fMax() {
    $A = func_get_args();
    $max = 0;
    foreach ($A as $v) {
    if ($v > $max) {
    $max = $v;
    }
    }
    return $max;
    }



    Третьим параметром указывается ассоциативный массив вида <имя функции> => callback. Так же может быть указан объект, аналогичный объекту для переменных.


    Дополнительный синтаксис

    Для более удобного вычисления нескольких выражений в одном контексте, а так же для эстетов, считающих данный синтаксис более правильным:

    $calc = new calculator();
    $calc->setContext($context);
    $calc->setFunctions($functions);
    print $calc->run($expression1).'<br />';
    print $calc->run($expression2).'<br />';
    print $calc->run($expression3).'<br />';



    Обработка ошибок

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

    В случае ошибок в выражении генерируются исключения. Производных классов для исключений не определено — все они от Exception.
    Коды исключений (которые можно получить методом getCode() объекта исключения):
    1 - деление на 0.
    2 - неизвестная переменная. Имя переменной можно получить из свойства "var".
    3 - неизвестная функция. Имя можно получить из "func".
    4 - ошибка синтаксиса. Часть ошибочного выражения находится в "expression".

    Пример с обработкой ошибок:


    function run($expression)
    {
    try {
    $res = calculator::calc($expression);
    print '<p>Result: '.$res.'</p>';
    } catch (Exception $e) {
    switch ($e->getCode()) {
    case 1:
    print '<p>Division by zero</p>';
    break;
    case 2:
    print '<p>Undefined variable: "'.htmlSpecialChars($e->var).'"</p>';
    break;
    case 3:
    print '<p>Undefined function: "'.htmlSpecialChars($e->func).'"</p>';
    break;
    case 4:
    print '<p>Parse error in "'.htmlSpecialChars($e->expression).'"</p>';
    break;
    }
    }

    }

    run('1/0');        // Division by zero
    run('1/x');        // Undefined variable: "x"
    run('1/x(1)');     // Undefined function: "x"
    run('2+3*(2+1+)'); // Parse error in "2+1+"
    run('2+3*(2+1))'); // Parse error in "2+3*3.0000)"

Пожалуйста, авторизуйтесь, чтобы написать комментарий!