Projekt

Obecné

Profil

Stáhnout (2.73 KB) Statistiky
| Větev: | Revize:
1
<?php
2

    
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11

    
12
namespace Symfony\Component\Translation;
13

    
14
/**
15
 * Tests if a given number belongs to a given math interval.
16
 *
17
 * An interval can represent a finite set of numbers:
18
 *
19
 *  {1,2,3,4}
20
 *
21
 * An interval can represent numbers between two numbers:
22
 *
23
 *  [1, +Inf]
24
 *  ]-1,2[
25
 *
26
 * The left delimiter can be [ (inclusive) or ] (exclusive).
27
 * The right delimiter can be [ (exclusive) or ] (inclusive).
28
 * Beside numbers, you can use -Inf and +Inf for the infinite.
29
 *
30
 * @author Fabien Potencier <fabien@symfony.com>
31
 *
32
 * @see    http://en.wikipedia.org/wiki/Interval_%28mathematics%29#The_ISO_notation
33
 */
34
class Interval
35
{
36
    /**
37
     * Tests if the given number is in the math interval.
38
     *
39
     * @param int    $number   A number
40
     * @param string $interval An interval
41
     *
42
     * @return bool
43
     *
44
     * @throws \InvalidArgumentException
45
     */
46
    public static function test($number, $interval)
47
    {
48
        $interval = trim($interval);
49

    
50
        if (!preg_match('/^'.self::getIntervalRegexp().'$/x', $interval, $matches)) {
51
            throw new \InvalidArgumentException(sprintf('"%s" is not a valid interval.', $interval));
52
        }
53

    
54
        if ($matches[1]) {
55
            foreach (explode(',', $matches[2]) as $n) {
56
                if ($number == $n) {
57
                    return true;
58
                }
59
            }
60
        } else {
61
            $leftNumber = self::convertNumber($matches['left']);
62
            $rightNumber = self::convertNumber($matches['right']);
63

    
64
            return
65
                ('[' === $matches['left_delimiter'] ? $number >= $leftNumber : $number > $leftNumber)
66
                && (']' === $matches['right_delimiter'] ? $number <= $rightNumber : $number < $rightNumber)
67
            ;
68
        }
69

    
70
        return false;
71
    }
72

    
73
    /**
74
     * Returns a Regexp that matches valid intervals.
75
     *
76
     * @return string A Regexp (without the delimiters)
77
     */
78
    public static function getIntervalRegexp()
79
    {
80
        return <<<EOF
81
        ({\s*
82
            (\-?\d+(\.\d+)?[\s*,\s*\-?\d+(\.\d+)?]*)
83
        \s*})
84

    
85
            |
86

    
87
        (?P<left_delimiter>[\[\]])
88
            \s*
89
            (?P<left>-Inf|\-?\d+(\.\d+)?)
90
            \s*,\s*
91
            (?P<right>\+?Inf|\-?\d+(\.\d+)?)
92
            \s*
93
        (?P<right_delimiter>[\[\]])
94
EOF;
95
    }
96

    
97
    private static function convertNumber($number)
98
    {
99
        if ('-Inf' === $number) {
100
            return log(0);
101
        } elseif ('+Inf' === $number || 'Inf' === $number) {
102
            return -log(0);
103
        }
104

    
105
        return (float) $number;
106
    }
107
}
(5-5/18)