Last active
August 16, 2017 11:46
-
-
Save Deuchnord/d0e259ad11d71b43b0209875e14cec0e to your computer and use it in GitHub Desktop.
Number to Roman digits and vice-versa converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Converts $n from Arabic digits to Roman digits. | |
* This is accurate from 1 to 4999 and only for integers, since the | |
* extensions to write the numbers greater than 4999 and the fractions are | |
* not implemented. | |
* Note that there is no way to write negative number ans zero, as they were | |
* not used by Roman. Plus, numbers are truncated to integers, so that 4.2 | |
* will be converted to IV. | |
* | |
* @param integer $n | |
* @return string | |
* @throws Exception If the number cannot be converted. | |
**/ | |
function arabic2roman($n) { | |
$n = (int) $n; | |
if($n < 1 || $n > 4999) | |
throw new Exception("Cannot convert $n to roman."); | |
$roman = ''; | |
while($n >= 1000) { | |
$roman .= 'M'; | |
$n -= 1000; | |
} | |
while($n >= 100) { | |
$roman .= 'C'; | |
$n -= 100; | |
} | |
$roman = str_replace('CCCCCCCCC', 'CM', $roman); | |
$roman = str_replace('CCCCC', 'D', $roman); | |
$roman = str_replace('CCCC', 'CD', $roman); | |
while($n >= 10) { | |
$roman .= 'X'; | |
$n -= 10; | |
} | |
$roman = str_replace('XXXXXXXXX', 'XC', $roman); | |
$roman = str_replace('XXXXX', 'L', $roman); | |
$roman = str_replace('XXXX', 'XL', $roman); | |
while($n > 0) { | |
$roman .= 'I'; | |
$n -= 1; | |
} | |
$roman = str_replace('IIIIIIIII', 'IX', $roman); | |
$roman = str_replace('IIIII', 'V', $roman); | |
$roman = str_replace('IIII', 'IV', $roman); | |
return $roman; | |
} | |
/** | |
* Converts $n from Roman digits to a number. | |
* | |
* @param string $n | |
* @param int The number which corresponds to $n | |
* @throws Exception If the number cannot be converted (especially because | |
* of a parse error) | |
**/ | |
function roman2arabic($n) { | |
$arabic = 0; | |
$pos = 0; | |
$n = strtoupper($n); | |
for($i = 0; $i < strlen($n); $i++) { | |
$digit = $n[$i]; | |
$nextdigit = $n[$i+1]; | |
switch($digit) { | |
case 'I': | |
if($nextdigit == 'X') { | |
$arabic += 9; | |
$i++; | |
continue; | |
} | |
elseif($nextdigit == 'V') { | |
$arabic += 4; | |
$i++; | |
continue; | |
} | |
$arabic += 1; | |
break; | |
case 'V': | |
$arabic += 5; | |
break; | |
case 'X': | |
if($nextdigit == 'L') { | |
$arabic += 40; | |
$i++; | |
continue; | |
} | |
if($nextdigit == 'C') { | |
$arabic += 90; | |
$i++; | |
continue; | |
} | |
$arabic += 10; | |
break; | |
case 'L': | |
$arabic += 50; | |
break; | |
case 'C': | |
if($nextdigit == 'D') { | |
$arabic += 400; | |
$i++; | |
continue; | |
} | |
if($nextdigit == 'M') { | |
$arabic += 900; | |
$i++; | |
continue; | |
} | |
$arabic += 100; | |
break; | |
case 'D': | |
$arabic += 500; | |
break; | |
case 'M': | |
$arabic += 1000; | |
break; | |
default: | |
throw new Exception("Parse error: $digit is not a valid Roman digit."); | |
} | |
} | |
return $arabic; | |
} | |
header('Content-Type: text/plain'); | |
for($i=1;$i<5000;$i++) | |
echo arabic2roman($i) . ' <=> ' . roman2arabic(arabic2roman($i)) . "\n"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment