programa - Números para números romanos con php
diagrama de flujo para convertir numeros arabigos a romanos (6)
COMPROBADO Y VERIFICADO POR LA UNIDAD DE PHP
Cree una clase con el nombre RomanNumerials y agregue una propiedad estática protegida tal como se define:
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'',
];
luego agrega un método de la siguiente manera
public function output ($number)
{
$solution = '''';
foreach(static::$lookup as $limit => $glyph){
while ($number >= $limit) {
$solution .= $glyph;
$number -= $limit;
}
}
return $solution;
}
Necesito transformar números ordinarios a números romanos con php y tengo este código:
<?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);
?>
prueba de esta manera pero no funciona:
echo $s=number2roman((.$row[''id''].),true);
echo "/n and bacK:/n";
echo roman2number($s);
el problema es que necesito cambiar los números son lecturas de mi base de datos sql y no sé cómo hacerlo, desde y hasta.
Encontré este código aquí: http://php.net/manual/en/function.base-convert.php
Función optimizada y embellecida:
/**
* @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;
}
Hay un problema de compensación ilegal.
Reemplazar
$o=1:$b].$s);
con
$o=1:$b >0 ? $b : 0].$s);
Mira mi solución aquí https://github.com/frostymarvelous/Whisppa-Libs/blob/master/Misc/Numeralo.php . Funciona en ambos sentidos.
<?php
/**
* @package Whisppa
* @subpackage Misc
* @license http://opensource.org/licenses/MIT MIT License
* @author Stefan (frostymarvelous) Froelich <[email protected]>
* @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;
}
}
Otra forma de hacerlo
<?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