* @since 1.0.0 */ public const ROMANS = [ 'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1, ]; /** * Constructor. * * @since 1.0.0 * @codeCoverageIgnore */ private function __construct() { } /** * Convert base. * * @param string $numberInput Input number * @param string $fromBaseInput Input layout (e.g. 0123456789ABCDEF) * @param string $toBaseInput Output layout (e.g. 0123456789ABCDEF) * * @return string * * @since 1.0.0 */ public static function convertBase(string $numberInput, string $fromBaseInput, string $toBaseInput) : string { if ($fromBaseInput === $toBaseInput) { return $numberInput; } $fromBase = \str_split($fromBaseInput, 1); $toBase = \str_split($toBaseInput, 1); $number = \str_split($numberInput, 1); $fromLen = \strlen($fromBaseInput); $toLen = \strlen($toBaseInput); $numberLen = \strlen($numberInput); $newOutput = ''; if ($toBaseInput === '0123456789') { $newOutput = '0'; for ($i = 1; $i <= $numberLen; ++$i) { $newOutput = \bcadd( $newOutput, \bcmul( (string) \array_search($number[$i - 1], $fromBase), \bcpow((string) $fromLen, (string) ($numberLen - $i)) ) ); } return $newOutput; } $base10 = (int) ($fromBaseInput !== '0123456789' ? self::convertBase($numberInput, $fromBaseInput, '0123456789') : $numberInput); if ($base10 < \strlen($toBaseInput)) { return $toBase[$base10]; } while ($base10 !== '0') { $newOutput = $toBase[(int) \bcmod((string) $base10, (string) $toLen)] . $newOutput; $base10 = \bcdiv((string) $base10, (string) $toLen, 0); } return $newOutput; } /** * Convert arabic to roman. * * Be aware that there is no standard for larger roman numbers. * * @param int $arabic Arabic number * * @return string * * @since 1.0.0 */ public static function arabicToRoman(int $arabic) : string { $result = ''; while ($arabic > 0) { foreach (self::ROMANS as $rom => $arb) { if ($arabic >= $arb) { $arabic -= $arb; $result .= $rom; break; } } } return $result; } /** * Convert roman to arabic. * * @param string $roman Roman number * * @return int * * @since 1.0.0 */ public static function romanToArabic(string $roman) : int { $result = 0; foreach (self::ROMANS as $key => $value) { while (\str_starts_with($roman, $key)) { $result += $value; $temp = \substr($roman, \strlen($key)); if ($temp !== false) { $roman = $temp; } } } return $result; } /** * Convert numeric to alpha. * * This can be used for alpha lists such as e.g. word uses. * * @param int $number Number to convert * * @return string * * @since 1.0.0 */ public static function numericToAlpha(int $number) : string { $alpha = ''; for ($i = 1; $number >= 0 && $i < 10; ++$i) { $alpha = \chr(0x41 + (int) ($number % \pow(26, $i) / \pow(26, $i - 1))) . $alpha; $number -= \pow(26, $i); } return $alpha; } /** * Convert alpha to numeric. * * @param string $alpha Alpha to convert * * @return int * * @since 1.0.0 */ public static function alphaToNumeric(string $alpha) : int { $numeric = 0; $length = \strlen($alpha); for ($i = 0; $i < $length; ++$i) { $numeric += \pow(26, $i) * (\ord($alpha[$length - $i - 1]) - 0x40); } return (int) $numeric - 1; } }