3 namespace Mpdf\Conversion
;
6 * @link https://github.com/JeroenDeDauw/RomanNumbers
14 public function __construct(array $symbolMap = [])
16 if ($symbolMap !== []) {
17 $this->symbolMap
= $symbolMap;
19 $this->symbolMap
= [['I', 'V'], ['X', 'L'], ['C', 'D'], ['M']];
23 public function convert($number)
25 $this->ensureNumberIsAnInteger($number);
26 $this->ensureNumberIsWithinBounds($number);
28 return $this->constructRomanString($number);
31 private function ensureNumberIsAnInteger($number)
33 if (!is_int($number)) {
34 throw new \
InvalidArgumentException('Can only translate integers to roman');
38 private function ensureNumberIsWithinBounds($number)
41 throw new \
OutOfRangeException('Numbers under one cannot be translated to roman');
44 if ($number > $this->getUpperBound()) {
45 throw new \
OutOfBoundsException('The provided number is to big to be fully translated to roman');
49 public function getUpperBound()
51 $symbolGroupCount = count($this->symbolMap
);
52 $valueOfOne = 10 ** ($symbolGroupCount - 1);
54 $hasFiveSymbol = array_key_exists(1, $this->symbolMap
[$symbolGroupCount - 1]);
56 return $valueOfOne * ($hasFiveSymbol ?
9 : 4) - 1;
59 private function constructRomanString($number)
63 $symbolMapCount = count($this->symbolMap
);
64 for ($i = 0; $i < $symbolMapCount; $i++
) {
65 $divisor = 10 ** ($i +
1);
66 $remainder = $number %
$divisor;
67 $digit = $remainder / (10 ** $i);
69 $number -= $remainder;
70 $romanNumber = $this->formatDigit($digit, $i) . $romanNumber;
80 private function formatDigit($digit, $orderOfMagnitude)
86 if ($digit === 4 ||
$digit === 9) {
87 return $this->formatFourOrNine($digit, $orderOfMagnitude);
94 $romanNumber .= $this->getFiveSymbol($orderOfMagnitude);
97 $romanNumber .= $this->formatOneToThree($orderOfMagnitude, $digit);
102 private function formatFourOrNine($digit, $orderOfMagnitude)
104 $firstSymbol = $this->getOneSymbol($orderOfMagnitude);
105 $secondSymbol = $digit === 4
106 ?
$this->getFiveSymbol($orderOfMagnitude)
107 : $this->getTenSymbol($orderOfMagnitude);
109 return $firstSymbol . $secondSymbol;
112 private function formatOneToThree($orderOfMagnitude, $digit)
114 return str_repeat($this->getOneSymbol($orderOfMagnitude), $digit);
117 private function getOneSymbol($orderOfMagnitude)
119 return $this->symbolMap
[$orderOfMagnitude][0];
122 private function getFiveSymbol($orderOfMagnitude)
124 return $this->symbolMap
[$orderOfMagnitude][1];
127 private function getTenSymbol($orderOfMagnitude)
129 return $this->symbolMap
[$orderOfMagnitude +
1][0];