Мне нужно преобразовать обычные числа в римские цифры с php, и у меня есть этот код:
<?php function roman2number($roman){ $conv = array( array("letter" => 'I', "number" => 1), array("letter" => 'V', "number" => 5), array("letter" => 'X', "number" => 10), array("letter" => 'L', "number" => 50), array("letter" => 'C', "number" => 100), array("letter" => 'D', "number" => 500), array("letter" => 'M', "number" => 1000), array("letter" => 0, "number" => 0) ); $arabic = 0; $state = 0; $sidx = 0; $len = strlen($roman); while ($len >= 0) { $i = 0; $sidx = $len; while ($conv[$i]['number'] > 0) { if (strtoupper(@$roman[$sidx]) == $conv[$i]['letter']) { if ($state > $conv[$i]['number']) { $arabic -= $conv[$i]['number']; } else { $arabic += $conv[$i]['number']; $state = $conv[$i]['number']; } } $i++; } $len--; } return($arabic); } function number2roman($num,$isUpper=true) { $n = intval($num); $res = ''; /*** roman_numerals array ***/ $roman_numerals = array( 'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1 ); foreach ($roman_numerals as $roman => $number) { /*** divide to get matches ***/ $matches = intval($n / $number); /*** assign the roman char * $matches ***/ $res .= str_repeat($roman, $matches); /*** substract from the number ***/ $n = $n % $number; } /*** return the res ***/ if($isUpper) return $res; else return strtolower($res); } /* TEST */ echo $s=number2roman(6,true); echo "\n and bacK:\n"; echo roman2number($s); ?>
попробуйте этот путь, но не работает:
echo $s=number2roman((.$row['id'].),true); echo "\n and bacK:\n"; echo roman2number($s);
проблема в том, что мне нужно изменить числа, это чтение моей базы данных sql и не знаю, как это сделать, от и до конца.
Я нашел этот код здесь: http://php.net/manual/en/function.base-convert.php
Оптимизированная и предустановленная функция:
/** * @param int $number * @return string */ function numberToRomanRepresentation($number) { $map = array('M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1); $returnValue = ''; while ($number > 0) { foreach ($map as $roman => $int) { if($number >= $int) { $number -= $int; $returnValue .= $roman; break; } } } return $returnValue; }
Другой способ сделать это
<?php function ConverToRoman($num){ $n = intval($num); $res = ''; //array of roman numbers $romanNumber_Array = array( 'M' => 1000, 'CM' => 900, 'D' => 500, 'CD' => 400, 'C' => 100, 'XC' => 90, 'L' => 50, 'XL' => 40, 'X' => 10, 'IX' => 9, 'V' => 5, 'IV' => 4, 'I' => 1); foreach ($romanNumber_Array as $roman => $number){ //divide to get matches $matches = intval($n / $number); //assign the roman char * $matches $res .= str_repeat($roman, $matches); //substract from the number $n = $n % $number; } // return the result return $res; } echo ConverToRoman(23); ?>
function rome($N){ $c='IVXLCDM'; for($a=5,$b=$s='';$N;$b++,$a^=7) for($o=$N%$a,$N=$N/$a^0;$o--;$s=$c[$o>2?$b+$N-($N&=-2)+$o=1:$b].$s); return $s; } // from polish wiki
Проверьте мое решение здесь https://github.com/frostymarvelous/Whisppa-Libs/blob/master/Misc/Numeralo.php . Он работает в обоих направлениях.
<?php /** * @package Whisppa * @subpackage Misc * @license http://opensource.org/licenses/MIT MIT License * @author Stefan (frostymarvelous) Froelich <sfroelich@gmail.com> * @copyright Copyright (c) 2015, Stefan (frostymarvelous) Froelich */ namespace Whisppa\Misc; /** * This class allows you to convert from Roman numerals to natural numbers and vice versa. * I decided to do this as a fun challenge after reading http://thedailywtf.com/articles/Roman-Enumeration * Took me about 30 minutes to come up with, research and code the solution. * It can convert numbers up to 3,999,999 because I couldn't find any numerals for 5,000,000 above. * Due to my inability to get the correct accented characters 5000 above, I resulted to using the pipe (|) to represent accent. */ class Numeralo { /** * @var string[] A notation map to represent the common Roman numeral values. * @static */ protected static $NOTATION = [ '|', //one '[', //five ']', //ten ]; /** * @var \ArrayObject[] A map of Roman numerals based on place value. Each item ends with the first numeral in the next place value. * @static */ protected static $NUMERALS_BY_PLACE_VALUE = [ ['I', 'V', 'X',], //ones ['X', 'L', 'C',], //tens ['C', 'D', 'M',], // hundreds ['M', 'V|', 'X|',], //thousands ['X|', 'L|', 'C|',], //tens of thousands ['C|', 'D|', 'M|',], //hundreds of thousands ['M|', '~', '~',], // millions. there are no values for the last two that I could find ]; /** * @var string[] sA map of numbers and their representative Roman numerals in notation format. This map allows us to make any numeral by replacing the the notation with the place value equivalent. * @static */ protected static $NUMBER_TO_NOTATION = [ '0' => '', '1' => '|', '2' => '||', '3' => '
', '4' => '|[', '5' => '[', '6' => '[|', '7' => '[||', '8' => '[
', '9' => '|]', ]; /** * @var int[] A map of the major Roman numerals and the number equivalent. * @static */ protected static $NUMERALS_TO_NUMBER = [ 'I' => 1, 'V' => 5, 'X' => 10, 'L' => 50, 'C' => 100, 'D' => 500, 'M' => 1000, 'V|' => 5000, 'X|' => 10000, 'L|' => 50000, 'C|' => 100000, 'D|' => 500000, 'M|' => 1000000, ]; /** * Converts natural numbers to Roman numerals. * * @static * @param int|string $number a number or numeric string less than 3,999,999 * @throws \InvalidArgumentException if the provided $number argument is not numeric or greater than 3,999,999. * @return string Roman numeral equivalent */ public static function number_to_numerals($number) { if(!is_numeric($number)) throw new \InvalidArgumentException('Only numbers allowed'); if($number > 3999999) throw new \InvalidArgumentException('Number cannot be greater than 3,999,999'); $numerals = ''; $number_string = strrev((string) $number); $length = strlen($number_string); for($i = 0; $i < $length; $i++) { $char = $number_string[$i]; $num_map = self::$NUMERALS_BY_PLACE_VALUE[$i]; $numerals = str_replace(self::$NOTATION, $num_map, self::$NUMBER_TO_NOTATION[$char]) . $numerals; } return $numerals; } /** * Converts Roman numerals to natural numbers. * * @static * @param string $numerals the Roman numerals to be converted * @throws \InvalidArgumentException if the provided $numerals argument contains invalid characters. * @return int the equivalent number */ public static function numerals_to_number($numerals) { $number = 0; $numeral_string = strrev((string) $numerals); $length = strlen($numeral_string); $prev_number = false; $is_accented = false; for($i = 0; $i < $length; $i++) { $char = $numeral_string[$i]; if($char == '|') //check if it is an accent character { $is_accented = true; continue;//skip this iteration and process it in the next one as the accent applies to the next char } else if($is_accented) { $char .= '|'; $is_accented = false; } //TODO Make a check using maybe regex at the beginning of the method. if(!isset(self::$NUMERALS_TO_NUMBER[$char])) throw new \InvalidArgumentException("Invalid character '{$char}' in numeral string"); $num = self::$NUMERALS_TO_NUMBER[$char]; //this is where the magic happens //if the previous number divided by 5 or 10 is equal to the current number, then we subtract eg. 9 = IX. I = 1, X = 10, 10/10 = 1 if($prev_number) { if(($prev_number / 5) == $num || ($prev_number / 10) == $num) $number -= $num; else $number += $num; } else $number += $num; $prev_number = $num; } return $number; } }
Существует проблема незаконного смещения.
замещать
$o=1:$b].$s);
с
$o=1:$b >0 ? $b : 0].$s);
ПРОВЕРЕН И ПРОВЕРЕН С помощью PHP-модуля
Создайте класс с именем RomanNumerials и добавьте защищенное статическое свойство, как определено:
protected static $lookup = [ 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', ];
затем добавьте метод следующим образом
public function output ($number) { $solution = ''; foreach(static::$lookup as $limit => $glyph){ while ($number >= $limit) { $solution .= $glyph; $number -= $limit; } } return $solution; }