MySQL Custom Function to Turn Roman Numeral Into Arabic

亡梦爱人 提交于 2019-12-06 09:25:23

Not sure why your isnt working but googling was fast and I came up with this link:

http://forge.mysql.com/tools/tool.php?id=107

CREATE FUNCTION fromRoman (inRoman varchar(15)) RETURNS integer DETERMINISTIC
BEGIN

    DECLARE numeral CHAR(7) DEFAULT 'IVXLCDM';

    DECLARE digit TINYINT;
    DECLARE previous INT DEFAULT 0;
    DECLARE current INT;
    DECLARE sum INT DEFAULT 0;

    SET inRoman = UPPER(inRoman);

    WHILE LENGTH(inRoman) > 0 DO
        SET digit := LOCATE(RIGHT(inRoman, 1), numeral) - 1;
        SET current := POW(10, FLOOR(digit / 2)) * POW(5, MOD(digit, 2));
        SET sum := sum + POW(-1, current < previous) * current;
        SET previous := current;
        SET inRoman = LEFT(inRoman, LENGTH(inRoman) - 1);
    END WHILE;

    RETURN sum;
END

I modified the function provided by Valentin to make it a little more robust.

It now: 1) Trims out white space before doing the roman numeral conversion. 2) Checks the incoming text for any characters not in a Roman numeral and returns -1 if this is the case.

Such that:

SELECT fromRoman('iv'), fromRoman('Mxii'), fromRoman(' iX'), 
       fromRoman('xi '), fromRoman('Hi');

Yields:

4  1012    9   11  -1

    CREATE FUNCTION fromRoman (inRoman varchar(15)) RETURNS integer DETERMINISTIC
      BEGIN
DECLARE numeral CHAR(7) DEFAULT 'IVXLCDM'; DECLARE digit TINYINT; DECLARE previous INT DEFAULT 0; DECLARE current INT; DECLARE sum INT DEFAULT 0;
  SET inRoman = UPPER(TRIM(inRoman));
  IF NOT inRoman REGEXP '[^IVXLCDM]+' THEN
    WHILE LENGTH(inRoman) > 0 DO
    SET digit := LOCATE(RIGHT(inRoman, 1), numeral) - 1;
    SET current := POW(10, FLOOR(digit / 2)) * POW(5, MOD(digit, 2));
    SET sum := sum + POW(-1, current < previous) * current;
    SET previous := current;
    SET inRoman = LEFT(inRoman, LENGTH(inRoman) - 1);
    END WHILE;

    RETURN sum;
  ELSE
    RETURN -1;
  END IF;
END

I know the question was perfectly answered, and maybe this should be a comment, but I came here looking for the inverse process, roman to arabic, so I had this function:

CREATE FUNCTION `toRoman`(inArabic int unsigned) RETURNS varchar(15) CHARSET latin1 DETERMINISTIC
BEGIN
    DECLARE numeral CHAR(7) DEFAULT 'IVXLCDM';

    DECLARE stringInUse CHAR(3);
    DECLARE position tinyint DEFAULT 1;
    DECLARE currentDigit tinyint;

    DECLARE returnValue VARCHAR(15) DEFAULT '';

    IF(inArabic > 3999) THEN RETURN 'overflow'; END IF;
    IF(inArabic = 0) THEN RETURN 'N'; END IF;

    WHILE position <= CEIL(LOG10(inArabic + .1)) DO
        SET currentDigit := MOD(FLOOR(inArabic / POW(10, position - 1)), 10);

        SET returnValue := CONCAT(
            CASE currentDigit
                WHEN 4 THEN CONCAT(SUBSTRING(numeral, position * 2 - 1, 1), SUBSTRING(numeral, position * 2, 1))
                WHEN 9 THEN CONCAT(SUBSTRING(numeral, position * 2 - 1, 1), SUBSTRING(numeral, position * 2 + 1, 1))
                ELSE CONCAT(
                    REPEAT(SUBSTRING(numeral, position * 2, 1), currentDigit >= 5),
                    REPEAT(SUBSTRING(numeral, position * 2 - 1, 1), MOD(currentDigit, 5))
                )
            END,
            returnValue);

        SET position := position + 1;
    END WHILE;
    RETURN returnValue;
END
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!