<?php

class Math
{
    public static function execute($operation, $args, $round = true)
    {
        preg_match('/:(\w+)/', $operation, $matches);

        if ($args[$matches[1]] == 0) {
            return 0;
        }

        $keys = array_map(function ($key) {
            return substr($key, 0, 1) === ':'
                ? $key
                : ':'.$key;
        }, array_keys($args));

        // Remueve espacios entre elementos
        $operation = preg_replace('/\s/', '', $operation);

        $formula = str_replace($keys, array_values($args), $operation);
        eval("\$res = ${formula};");

        if ($round) {
            return self::round($res);
        }

        return $res;
    }

    public static function round($number, $precision = 2)
    {
        $precision = ($precision < 0)
                   ? 0
                   : (int) $precision;
        if (strcmp(bcadd($number, '0', $precision), bcadd($number, '0', $precision + 1)) == 0) {
            return bcadd($number, '0', $precision);
        }
        if (self::getBcPresion($number) - $precision > 1) {
            $number = self::round($number, $precision + 1);
        }
        $t = '0.'.str_repeat('0', $precision).'5';

        return $number < 0
               ? bcsub($number, $t, $precision)
               : bcadd($number, $t, $precision);
    }

    public static function diff($a, $b)
    {
        return bccomp($a, $b, 2) > 0 || bccomp($a, $b, 2) < 0;
    }

    private static function getBcPresion($number)
    {
        $dotPosition = strpos($number, '.');
        if ($dotPosition === false) {
            return 0;
        }

        return strlen($number) - strpos($number, '.') - 1;
    }
}
