PHP Classes

File: libs/Dec2RomanNumConverter.php

Recommend this page to a friend!
  Classes of Nikola Posa   Dec2RomanNumConverter   libs/Dec2RomanNumConverter.php   Download  
File: libs/Dec2RomanNumConverter.php
Role: Class source
Content type: text/plain
Description: Class for converting decimal numbers to Roman numberals and vice-versa.
Class: Dec2RomanNumConverter
Convert numbers between decimal and roman
Author: By
Last change: - Improved algorithm
Date: 13 years ago
Size: 5,153 bytes
 

Contents

Class file image Download
<?php
/**
 * Dec2RomanNumConverter
 *
 * Copyright (C) 2009 Nikola Posa (http://www.nikolaposa.in.rs)
 *
 * This file is part of Dec2RomanNumConverter.
 *
 * Dec2RomanNumConverter is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Dec2RomanNumConverter is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Dec2RomanNumConverter. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * Class for converting decimal numbers to Roman numberals and
 * vice-versa.
 *
 * @author Nikola Posa, www.nikolaposa.in.rs
 * @license http://opensource.org/licenses/gpl-3.0.html GNU General Public License
 */
class Dec2RomanNumConverter
{
   
/**
     * Common Roman numerals array, with appropriate decimal
     * numbers as indexes.
     *
     * @var array
     */
   
protected static $_basicNumbers = array
    (
       
1 => 'I',
       
5 => 'V',
       
10 => 'X',
       
50 => 'L',
       
100 => 'C',
       
500 => 'D',
       
1000 => 'M'
   
);
   
   
/**
     * Method for converting decimal numbers to Roman numerals.
     *
     * @param int $decimalNumber
     * @return string
     */
   
public static function dec2roman($decimalNumber)
    {
       
$decimalNumber = (int)$decimalNumber;
       
       
//Cheks if argument is larger than 3999 as such numbers
        //require a bar above the base numeral.
       
if ($decimalNumber > 3999) {
            require_once
'Dec2RomanNumConverter/Exception.php';
            throw new
Dec2RomanNumConverter_Exception('Numbers larger than 3999 are not supported.');
        }
       
        if (
array_key_exists($decimalNumber, self::$_basicNumbers)) {
            return
self::$_basicNumbers[$decimalNumber];
        }
       
       
$romanNum = '';
       
       
$decNum = (string)$decimalNumber;
       
$decNumLength = strlen($decNum);

        for (
$i = 0; $i < $decNumLength; $i++) { //Looping through all numerals.
           
$currentNumber = (int)$decNum[$i];
            if (
$currentNumber == 0) {
                continue;
            }
           
           
$decPow = pow(10, ($decNumLength - 1 - $i));

            switch (
$currentNumber) {
                case
4: case 9: //4 and 9 are written using their higher base (5 or 10).
                   
$romanNum .=
                       
self::$_basicNumbers[$decPow]
                        .
self::$_basicNumbers[($currentNumber+1)*$decPow];
                    break;
                case
6: case 7: case 8: //4 and 9 are written using 5 (V) as a base.
                   
$romanNum .=
                       
self::$_basicNumbers[5*$decPow]
                        .
str_repeat(self::$_basicNumbers[$decPow], ($currentNumber-5));
                    break;
                case
5:
                   
$romanNum .= self::$_basicNumbers[5*$decPow];
                    break;
                default:
                   
$romanNum .= str_repeat(self::$_basicNumbers[$decPow], $currentNumber);
                    break;
            }
        }
       
        return
$romanNum;
    }
   
   
/**
     * Method for converting Roman numerals to decimal numbers.
     *
     * @param string $romanNumeral
     * @return int
     */
   
public static function roman2dec($romanNumeral)
    {
       
$romanNumeral = trim((string)$romanNumeral);
        if (!
preg_match('/^[' . implode('', array_values(self::$_basicNumbers)) . ']+$/i', $romanNumeral)) {
            require_once
'Dec2RomanNumConverter/Exception.php';
            throw new
Dec2RomanNumConverter_Exception('Roman numeral "' . $romanNumeral . '" is not valid or it is to large to handle.');
        }
       
       
$romanNumeral = strtoupper($romanNumeral);
       
       
$decNum = 0;

       
//Early return.
       
if (($decNum = array_search($romanNumeral, self::$_basicNumbers)) !== false) {
            return
$decNum;
        }

       
$count = 1;
       
$basicNumbers = array_flip(self::$_basicNumbers);
        for (
$i = 0; $i < strlen($romanNumeral); $i++) {
           
$dn = $basicNumbers[$romanNumeral[$i]];
           
$nextDn = (isset($romanNumeral[$i+1])) ? $basicNumbers[$romanNumeral[$i+1]] : null;

           
$decNum += $dn;

            if (
$nextDn !== null) {
                if (
$nextDn == $dn) {
                   
$count++;
                }
                elseif (
$nextDn > $dn) { //Special pattern (IV, IX, CM, etc.)?
                   
$temp = $dn * $count; //Value that will be substracted from higher base.
                   
$decNum -= $temp;
                   
$decNum += $nextDn - $temp;
                   
                   
$i++; //Skipping next numeral.
                   
$count = 1;
                }
                else {
                   
$count = 1;
                }
            }
        }
       
        return
$decNum;
    }
}