芝麻web文件管理V1.00
编辑当前文件:/home/strato/chroot/opt/RZphp5/includes/Numbers/Roman.php
| // | Sterling Hughes
| // +----------------------------------------------------------------------+ // $Id: Roman.php,v 1.20 2007/06/28 10:48:41 cweiske Exp $ // {{{ Numbers_Roman /** * Provides utilities to convert roman numerals to arabic numbers * and convert arabic numbers to roman numerals. * * @author David Costa
* @author Sterling Hughes
* @package Numbers_Roman */ /** * Needed for error handling */ require_once 'PEAR.php'; /** * Provides utilities to convert roman numerals to * arabic numbers and convert arabic numbers to roman numerals. * * Supports lower case input and output and some further conversion * functions. * * @access public * @author David Costa
* @author Sterling Hughes
* @package Numbers_Roman */ class Numbers_Roman { // {{{ toNumber() /** * Converts a roman numeral to a number * * @param string $roman The roman numeral to convert lower cased * numerals are converted into uppercase * @return integer $num The number corresponding to the * given roman numeral * @access public */ function toNumber($roman) { /* * insure that matching works */ $roman = strtoupper($roman); /* * remove all inapropriate characters */ $roman = preg_replace('/[^_MDCLXVUI]/', '', $roman); /* * replace u with v, in case the number being parsed * uses a variant character set */ $roman = str_replace('U', 'V', $roman); /* * Replacing the Numerals representing an integer higher then 4000 * e.g. _X represent 10 000 _L represent 50 000 etc * we first convert them into single characters */ $roman = str_replace('_V', 'S', $roman); $roman = str_replace('_X', 'R', $roman); $roman = str_replace('_L', 'P', $roman); $roman = str_replace('_C', 'Q', $roman); $roman = str_replace('_D', 'O', $roman); $roman = str_replace('_M', 'N', $roman); /* * now for the conversion table. * the characters must be precisely in the same order * as the number array members they represent. This way, * their position in the string precisely represents * the array key of the corresponding number. */ $conv_chars = 'IVXLCDMSRPQON0'; $conv = array( 1, 5, 10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000, 500000, 1000000, 0 ); /* * initialize variables */ $arabic = 0; $state = 0; $sidx = 0; $pos = 0; $len = strlen($roman) - 1; /* * the numeral string is processed from right to left. */ while ($len >= 0) { $sidx = $len; /* * finds the array key by checking the location * of the character in the string $conv_chars */ $pos = strpos($conv_chars, $roman[$sidx]); /* * If a character is not found in the string, * generate an error message using PEAR_Error */ if ($pos === false) { PEAR::raiseError('Numbers_Roman::toNumber error: Invalid characters in input',0, PEAR_ERROR_TRIGGER); } else { /* * if the precedingly processed numeral is higher, * subtract the value of the current numeral. */ if ($state > $conv[$pos]) { if (!$state2){ $arabic -= $conv[$pos]; $state2 = true; } else { PEAR::raiseError('Numbers_Roman::toNumber error: Invalid numeral order in input (multiple subtraction)',0, PEAR_ERROR_TRIGGER); } /* * else, add the value of the numeral to our number * and remember it for the if clause directly * preceding this else */ } else { $arabic += $conv[$pos]; $state = $conv[$pos]; $state2 = false; } } /* * move one place to the left */ $len--; } return $arabic; } // }}} // {{{ toRoman() /** * A backwards compatibility alias for toNumeral() * * @access private */ function toRoman($num, $uppercase = true) { return Numbers_Roman::toNumeral($num, $uppercase); } // }}} // {{{ toNumeral() /** * Converts a number to its roman numeral representation * * @param integer $num An integer between 0 and 3999 * inclusive that should be converted * to a roman numeral integers higher than * 3999 are supported from version 0.1.2 * Note: * For an accurate result the integer shouldn't be higher * than 5 999 999. Higher integers are still converted but * they do not reflect an historically correct Roman Numeral. * * @param bool $uppercase Uppercase output: default true * * @param bool $html Enable html overscore required for * integers over 3999. default true * @return string $roman The corresponding roman numeral * * @access public */ function toNumeral($num, $uppercase = true, $html = true) { $conv = array(10 => array('X', 'C', 'M'), 5 => array('V', 'L', 'D'), 1 => array('I', 'X', 'C')); $roman = ''; if ($num < 0) { return ''; } $num = (int) $num; $digit = (int) ($num / 1000); $num -= $digit * 1000; while ($digit > 0) { $roman .= 'M'; $digit--; } for ($i = 2; $i >= 0; $i--) { $power = pow(10, $i); $digit = (int) ($num / $power); $num -= $digit * $power; if (($digit == 9) || ($digit == 4)) { $roman .= $conv[1][$i] . $conv[$digit+1][$i]; } else { if ($digit >= 5) { $roman .= $conv[5][$i]; $digit -= 5; } while ($digit > 0) { $roman .= $conv[1][$i]; $digit--; } } } /* * Preparing the conversion of big integers over 3999. * One of the systems used by the Romans to represent 4000 and * bigger numbers was to add an overscore on the numerals. * Because of the non ansi equivalent if the html output option * is true we will return the overline in the html code if false * we will return a _ to represent the overscore to convert from * numeral to arabic we will always expect the _ as a * representation of the html overscore. */ if ($html == true) { $over = '
'; $overe = '
'; } elseif ($html == false) { $over = '_'; $overe = ''; } /* * Replacing the previously produced multiple MM with the * relevant numeral e.g. for 1 000 000 the roman numeral is _M * (overscore on the M) for 900 000 is _C_M (overscore on both * the C and the M) We initially set the replace to AFS which * will be later replaced with the M. * * 500 000 is _D (overscore D) in Roman Numeral * 400 000 is _C_D (overscore on both C and D) in Roman Numeral * 100 000 is _C (overscore C) in Roman Numeral * 90 000 is _X_C (overscore on both X and C) in Roman Numeral * 50 000 is _L (overscore L) in Roman Numeral * 40 000 is _X_L (overscore on both X and L) in Roman Numeral * 10 000 is _X (overscore X) in Roman Numeral * 5 000 is _V (overscore V) in Roman Numeral * 4 000 is M _V (overscore on the V only) in Roman Numeral * * For an accurate result the integer shouldn't be higher then * 5 999 999. Higher integers are still converted but they do not * reflect an historically correct Roman Numeral. */ $roman = str_replace(str_repeat('M', 1000), $over.'AFS'.$overe, $roman); $roman = str_replace(str_repeat('M', 900), $over.'C'.$overe.$over.'AFS'.$overe, $roman); $roman = str_replace(str_repeat('M', 500), $over.'D'.$overe, $roman); $roman = str_replace(str_repeat('M', 400), $over.'C'.$overe.$over.'D'.$overe, $roman); $roman = str_replace(str_repeat('M', 100), $over.'C'.$overe, $roman); $roman = str_replace(str_repeat('M', 90), $over.'X'.$overe.$over.'C'.$overe, $roman); $roman = str_replace(str_repeat('M', 50), $over.'L'.$overe, $roman); $roman = str_replace(str_repeat('M', 40), $over.'X'.$overe.$over.'L'.$overe, $roman); $roman = str_replace(str_repeat('M', 10), $over.'X'.$overe, $roman); $roman = str_replace(str_repeat('M', 5), $over.'V'.$overe, $roman); $roman = str_replace(str_repeat('M', 4), 'M'.$over.'V'.$overe, $roman); /* * Replacing AFS with M used in both 1 000 000 * and 900 000 */ $roman = str_replace('AFS', 'M', $roman); /* * Make HTML output more readable by combining span tags * where possible. */ if ($html == true) { $roman = str_replace($overe.$over, '', $roman); } /* * Checking for lowercase output */ if ($uppercase == false) { $roman = strtolower($roman); } return $roman; } // }}} } // }}} /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: */ ?>