Converts arabic numerals (1-3999) to roman numerals.

@param  int                       $int Arabic numeral to convert
@throws \InvalidArgumentException
@return string
481781
public static function arabic2roman(int $int): string
	{
		$int = (int) $int;

		if($int < 1 || $int > 3999)
		{
			throw new InvalidArgumentException('The number must be between 1 and 3999.');
		}

		$numerals =
		[
			'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,
		];

		$romanNumeral = '';

		foreach($numerals as $roman => $arabic)
		{
			$count = (int) ($int / $arabic);

			if($count === 0)
			{
				continue;
			}

			$romanNumeral .= str_repeat($roman, $count);

			$int %= $arabic;

			if($int === 0)
			{
				break;
			}
		}

		return $romanNumeral;
	}
1129396
private static function num2str(int $num):string
    {
        if ($num > 0 && $num < 160) {
            return chr($num);
        } elseif ($num < -20319 || $num > -10247) {
            return '';
        } else {
            $total = sizeof(self::$lib) - 1;
            for ($i = $total; $i >= 0; $i--) {
                if (self::$lib[$i][1] <= $num) {
                    break;
                }
            }
            return self::$lib[$i][0];
        }
    }
543014
public static function fromYear(int $year): string
    {
        // note this checks SeasonYearParam::FORMAT (YYYY), not self::FORMAT
        if (preg_match(SeasonYearParam::FORMAT, (string) $year) !== 1) {
            throw new \InvalidArgumentException('Year must be an integer in YYYY format');
        }

        return $year.'-'.substr((string) ($year + 1), -2);
    }
110659
def romanNumeral(n):
    
    if 0 > n > 4000: raise ValueError('``n`` must lie between 1 and 3999: %d' % n)
    roman   = 'I IV  V  IX  X  XL   L  XC    C   CD    D   CM     M'.split()
    arabic  = [1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000]
    res = []
    while n>0:
        pos = bisect.bisect_right(arabic, n)-1
        fit = n//arabic[pos]
        res.append(roman[pos]*fit); n -= fit * arabic[pos]
    return "".join(res)
946887
public static function toInt($roman)
    {
        if (!preg_match('`[MDCLXVI]+`', strtoupper($roman))) {
            throw new \InvalidArgumentException("$roman is an invalid roman numeral.");
        }
        $roman = strtoupper($roman);

        $characters = array_flip(self::$characters);

        $int = 0;
        while (strlen($roman) > 0) {
            if (isset($characters[substr($roman, 0, 2)])) {
                $int += $characters[substr($roman, 0, 2)];
                $roman = substr($roman, 2);
                continue;
            }
            if (isset($characters[substr($roman, 0, 1)])) {
                $int += $characters[substr($roman, 0, 1)];
                $roman = substr($roman, 1);
                continue;
            }
        }

        return $int;
    }
793889
public static function isInt($value) {
        if(is_object($value)) {
            $value = Assert::isString($value);
        }
        if(is_int($value)) {
            return $value;
        } elseif(is_scalar($value) && preg_match('@^-?[0-9]+$@', $value)) {
            return (int)$value;
        } else {
            throw new \InvalidArgumentException('Must be Int: ' . print_r($value, true));
        }
    }
574011
public static function upperRoman(int $num): string
    {
        $roman = '';

        $map = [
            '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
        ];

        foreach ($map as $k => $v) {
            while ($num >= $v) {
                $roman .= $k;
                $num -= $v;
            }
        }

        return $roman;
    }
994426
private function int3Type4($Int)
    {
        $Tail = $Int % 10;
        $Tail2 = $Int % 100;
        if ($Tail === 1 && $Tail2 !== 11) {
            return 0;
        }
        return ($Tail >= 2 && $Tail <= 4 && ($Tail2 < 10 || $Tail2 >= 20)) ? 1 : 2;
    }
772718
public static function roman2arabic(string $str): int
	{
		if(empty($str) || preg_match('/^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/i', $str) === 0)
		{
			throw new InvalidArgumentException('Invalid roman numeral. Only values between I and MMMCMXCIX are allowed.');
		}

		$numerals =
		[
			'M'  => 1000,
			'D'  => 500,
			'C'  => 100,
			'L'  => 50,
			'X'  => 10,
			'V'  => 5,
			'I'  => 1,
		];

		$arabicNumeral = 0;

		$previous = 0;

		foreach(str_split($str) as $numeral)
		{
			$arabicNumeral += $numerals[$numeral];

			if($previous < $numerals[$numeral])
			{
				$arabicNumeral -= ($previous * 2);
			}

			$previous = $numerals[$numeral];
		}

		return $arabicNumeral;
	}
1268940
static function romanNumeral( $num ) {
		static $table = array(
			array( '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X' ),
			array( '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', 'C' ),
			array( '', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', 'M' ),
			array( '', 'M', 'MM', 'MMM' )
		);

		$num = intval( $num );
		if ( $num > 3000 || $num <= 0 ) {
			return $num;
		}

		$s = '';
		for ( $pow10 = 1000, $i = 3; $i >= 0; $pow10 /= 10, $i-- ) {
			if ( $num >= $pow10 ) {
				$s .= $table[$i][floor( $num / $pow10 )];
			}
			$num = $num % $pow10;
		}
		return $s;
	}
791939
public static function encode($num)
    {
        $str = '';
        while ($num > 0) {
            $str = self::ALPHABET[($num % self::BASE)] . $str;
            $num = (int)($num / self::BASE);
        }
        return $str;
    }
340812
public static function toRoman(int $num) : string
    {
        $result = '';
        foreach (self::$romans as $roman => $value) {
            $matches = intval($num / $value);
            $result .= str_repeat($roman, $matches);
            $num     = $num % $value;
        }
        return $result;
    }
380127
private function intToByteString(int $int): string
    {
        $result = [];
        while (0 !== $int) {
            $result[] = chr($int & 0xFF);
            $int >>= 8;
        }
        
        return str_pad(implode(array_reverse($result)), 8, "\000", STR_PAD_LEFT);
    }
902670
protected function pack_int($int) {
        if (PHP_INT_SIZE === 8) {
            $left = 0xffffffff00000000;
            $right = 0x00000000ffffffff;
            $l = ($int & $left) >>32;
            $r = $int & $right;

            return pack('NN', $l, $r);
        } else {
            return pack('NN', 0, $int);
        }
    }
692276
public static function intBytes($int)
    {
        $intbytes = "";

        if ($int > 0xFFFF) {
            $intbytes = "\x12".pack("N", $int); // 4 byte integer
        } elseif ($int > 0xFF) {
            $intbytes = "\x11".pack("n", $int); // 2 byte integer
        } else {
            $intbytes = "\x10".pack("C", $int); // 8 byte integer
        }

        return $intbytes;
    }
805320
public static function convertId($id)
    {
        if (strlen($id) === 17) {
            $converted = substr($id, 3) - 61197960265728;
        } else {
            $converted = '765' . ($id + 61197960265728);
        }
        return (string)$converted;
    }
257927
private function convertInt($value)
    {
        if (!is_numeric($value)) {
            return $value;
        }

        if ((string) (int) $value !== (string) $value) {
            return $value;
        }

        return (int) $value;
    }