Romeinse cijfers
Hieronder staan 2 functies. De ene om een Arabisch cijfer (ons cijfersysteem, 0-9) naar een Romeins cijfer te veranderen, de anderen om een Romeins cijfer terug naar een Arabisch cijfer te veranderen. Romeinse cijfers gaan van 1 tot x. Ze kennen geen 0 (voor zover ik weet). Arabische cijfers gaan van -x tot x. Dus de invoer van Arabische cijfers moet positief zijn. Bij deze functies heb ik op de prestatie gelet. Ik mijn functie hiervoor geoptimaliseerd: De eerste functie genereerde alles : zelfs dat IV 4 is. De array bevatte alleen I, V, X, L, C, D en M. Maar dit was 3x zo traag dan onderstaande functies. Het verschil is echter amper merkbaar als je de functie 1x aanroept. Maar als je deze 2000x aanroept is er een groot verschil. (Wie roept deze functie 2000x aan? Ik heb geen idee.) Om de snelheid te bevorderen geef ik de array ook telkens mee in de function-arguments: Ik verwijder de array-delen die al geweest zijn. Als namelijk bij de eerste keer een getal kleiner is dan 50, dan maak je het getal kleiner. Dan zal de tweede keer het getal ook kleiner zijn dan 50. Logisch. Er zijn romeinse cijfers die groter zijn dan 1000 (D). Deze worden eigenlijk gemaakt door het rijtje van I, V, X, L, C, D en M opnieuw te doen, alleen dan met een streepje erboven. Dit heb ik echter niet gedaan, omdat ik zelf geen getallen boven de 1000 nodig zal hebben. En ik denk dat de meesten van jullie dato ook niet nodig hebben.
<?php
// Van getal naar romeins cijfer.
function int2roman ($num, $array = array(1000 => 'M', 900 => 'CM', 500 => 'D', 400 => 'CD', 100 => 'C', 90 => 'XC', 50 => 'L', 40 => 'XL', 10 => 'X', 9 => 'IX', 5 => 'V', 4 => 'IV', 1 => 'I')) {
$char = '';
if (is_int($num) && $num > 0) { // Als $num geen getal is, dan werkt het script niet en returnt hij $char, die leeg is.
foreach ($array as $key => $char) {
if ($num >= $key) {
break; // num is groter/gelijk aan de waarde van deze letter ($char). Breek uit!
}
unset($array[$key]); // De array word kleiner, omdat deze recursief doorgegeven word -> De foreach hoeft dus minder rijen af -> sneller.
}
$char .= int2roman(($num-$key), $array); // $char is al gedefinieerd, bij de uitgebroken foreach. Omdat romeinse cijfers vaak combinaties van letters zijn, moeten we recursief alles opnieuw doen.
}
return $char;
}
// Van romeins cijfer naar getal. (bovenstaande commentaar geld ook voor deze functie, alleen dan omgedraaid)
function roman2int ($rom, $array = array(1000 => 'M', 900 => 'CM', 500 => 'D', 400 => 'CD', 100 => 'C', 90 => 'XC', 50 => 'L', 40 => 'XL', 10 => 'X', 9 => 'IX', 5 => 'V', 4 => 'IV', 1 => 'I')) {
$num = '';
if (preg_match('#^(M|D|C|L|X|V|I)+$#', $rom) && strlen($rom) > 0) {
foreach ($array as $num => $char) {
if (preg_match('#^'.$char.'#', $rom)) {
$rom = preg_replace('#^'.$char.'#', '', $rom, 1);
break;
}
unset($array[$num]);
}
$num += roman2int($rom, $array);
}
return $num;
}
?>
Reacties
0