Конвертирование арабских цифр в римские
Класс позволяющий конвертировать арабский цифры в римские.
/*************************************************************
* Arabic/Roman Numeral Convertor *
* *
* For converting between integers and Roman Numerals as well *
* as checking the validity of Roman Numerals. *
* *
* 1 I *
* 5 V 5,000 V *
* 10 X 10,000 X *
* 50 L 50,000 L *
* 100 C 100,000 C *
* 500 D 500,000 D *
* 1000 M 1,000,000 M *
* *
* Copyright (C) Dmitry Zarezenko, 2005 *
* E-mail : DIKGenius_php@rambler.ru *
*************************************************************/
class ArRoConvertor{
// Constructor
function __construct (){
}
/***********************************
* These first arrays are used by *
* the functions which convert *
* roman numerals into arabic. *
***********************************/
var $counter= Array();
var $romans = Array("I" => 1, "V" => 5, "X" => 10, "L" => 50, "C" => 100, "D" => 500, "M" => 1000, "" => 0);
var $subs = Array("I" => true, "X" => true, "C" => true, "M" => true);
/***********************************
* This first function is a pretty *
* simple and generic function used *
* to define and throw errors *
***********************************/
function createError($ErrorName, $ErrorMessage) {
$theError = new Error();
$theError->name = $ErrorName;
$theError->message = $ErrorMessage;
$theError->throw();
}
/***********************************
* These next four functions are *
* used to test for errors in the *
* input and convert roman numerals *
* into arabic integers. *
***********************************/
function checkRom($Rcur, $Rnext, $lSub, $n, $l) {
if (!isSet($this->romans[$Rcur]) || (!isSet($this->romans[$Rnext]) && (($n+1) < $l))) {
$this->createError("InputError", "Not a Roman Numeral");
}
else if ($this->romans[$Rcur] >= $lSub) {
$this->createError("InputError", "Not a Properly Formed Numeral");
}
}
function testSub($cR, $nR, $pR) {
if (isSet ($this->romans[$cR]) && isSet ($this->romans[$nR]) && isSet ($this->romans[$pR])){
if ($this->romans[$cR] < $this->romans[$nR]) {
if (($this->romans[$pR] == $this->romans[$nR]) && ($this->subs[$nR] != true)) {
$this->createError("InputError", "Not a Properly Formed Numeral");
}
else if (($this->subs[$cR] == true) && (10*$this->romans[$cR] >= $this->romans[$nR])) {
return true;
}
else {
$this->createError("InputError", "Not a Properly Formed Numeral");
return false;
}
}
}
return false;
}
function testRom($rome) {
if (!isSet ($this->counter[$rome])) return false;
if ($this->counter[$rome] < 3) {
return true;
}
else {
$this->createError("InputError", "Not a Properly Formed Numeral");
}
return false;
}
function RomanToArabic ($rNumb) {
$this->counter["I"] = 0;
$this->counter["V"] = 2;
$this->counter["X"] = 0;
$this->counter["L"] = 2;
$this->counter["C"] = 0;
$this->counter["D"] = 2;
$this->counter["M"] = -1000000000; // Negative infinity
$intNumb = 0;
$lastNumb = 1000000000; // Positive infinity
$thisNumb = 0;
$lastSub = 1000000000; // Positive infinity
$rNumb= strtoupper ($rNumb);
/*$tmpNumb= preg_replace ( "/[^IVXLCDM]/m", '', $rNumb);
if ($tmpNumb!= $rNumb) $this->createError("Warning", "$rNumb is not a Roman numeral, was changed on $tmpNumb");
$rNumb= $tmpNumb;*/
$len= strlen ($rNumb);
for ($i= 0; $i< $len; $i++){
$currentR = $rNumb[$i];
@$nextR = $rNumb[$i+1];
@$prevR = $rNumb[$i-1];
$this->checkRom ($currentR, $nextR, $lastSub, $i, $len);
if ($this->testSub ($currentR, $nextR, $prevR)) {
$thisNumb = $this->romans[$nextR] - $this->romans[$currentR];
$i ++;
$lastSub = $this->romans[$currentR];
}
else if ($this->testRom($currentR)){
$thisNumb = $this->romans[$currentR];
$this->counter[$currentR] ++;
}
if ($thisNumb > $lastNumb) {
$this->createError("InputError", "Not a Properly Formed Numeral");
}
else {
$intNumb += $thisNumb;
$lastNumb = $thisNumb;
}
}
return $intNumb;
}
/***********************************
* The next two functions are used *
* for converting an arabic integer *
* into a roman Numeral. *
***********************************/
function Cut($num, $n){
return ($num - ($num % $n ) ) / $n;
}
function ArabicToRoman ($aNumb) {
if (!is_int ($aNumb)){
$this->createError("InputError", "$aNumb is not a Arabic Integer");
return "";
}
$rNumb= "";
while ($aNumb> 5999) { $rNumb.= "M"; $aNumb-= 1000;}
if(($aNumb > 0)) {
$mill = Array("", "M", "MM", "MMM", "MMMM", "MMMMM");
$cent = Array("", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM");
$tens = Array("", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC");
$ones = Array("", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX");
$m = $this->Cut($aNumb, 1000); $aNumb%= 1000;
$c = $this->Cut($aNumb, 100); $aNumb%= 100;
$t = $this->Cut($aNumb, 10); $aNumb%= 10;
return $rNumb . $mill[$m] . $cent[$c] . $tens[$t] . $ones[$aNumb];
}
else {
$this->createError("InputError", "Numbers from 1 to 5999 only please.");
return "";
}
}
}
class Error{
var $name= "", $message= "";
function Error(){
}
function throw(){
print "<b>" . $this->name ." :</b> " . $this->message . "<br>\n";
}
}
$s = new ArRoConvertor();
print 'RomanToArabic: '.$str." = <b>" . $s->RomanToArabic($str) ."</b><br>\n";
print 'ArabicToRoman: '.$str." = <b>" . $s->ArabicToRoman( intval ($str)) ."</b><br>\n";
.
Прокомментировать/Отблагодарить