2011-11-04 143 views
2

好吧,我需要一個MySQL的函數,將轉換爲羅馬數字字符串:MySQL的自定義函數把羅馬數字翻譯成阿拉伯文

例如XXCVI

到其阿拉伯語的編號等同。關於爲什麼我需要它,我只是做了一個長長的故事。

基於一個PHP函數,有人發帖,我創建了下面的MySQL功能,但它似乎無休止地運行,我不知道爲什麼。 (我可能只是太累了)

任何人有任何線索,以什麼錯我的功能,或有更有效的方式來羅馬數字字符串轉換爲阿拉伯數字?

DROP FUNCTION IF EXISTS `romeToArabic`$$ 
CREATE DEFINER=`root`@`localhost` FUNCTION `romeToArabic`(roman_in VARCHAR(64)) RETURNS int(11) 
BEGIN 
    DECLARE numeral VARCHAR(2); 
    DECLARE int_val INT; 
    DECLARE roman VARCHAR(64); 
    DECLARE res INT; 
    DECLARE no_more_rows BOOLEAN; 
    DECLARE num_rows INT DEFAULT 0; 
    DECLARE roman_cur CURSOR FOR SELECT num, val FROM roman_numeral ORDER BY id; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rows = TRUE; 
    SET roman = UPPER(roman_in); 
    SET res = 0; 

    DROP TEMPORARY TABLE IF EXISTS roman_numeral; 
    CREATE TEMPORARY TABLE roman_numeral (
     `id` INT(8) NOT NULL AUTO_INCREMENT, 
     `num` varchar(2) DEFAULT NULL, 
     `val` int(8) NOT NULL, PRIMARY KEY (id)) ENGINE=MyISAM; 

    INSERT INTO roman_numeral (num, val) VALUES ('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); 

    OPEN roman_cur; 
    SELECT FOUND_ROWS() INTO num_rows; 

the_loop: 
    LOOP 
    FETCH roman_cur INTO numeral, int_val; 
    IF no_more_rows THEN CLOSE roman_cur; 
     LEAVE the_loop; 
    END IF; 

    WHILE INSTR(roman, numeral) = 1 DO 
     SET res = res + int_val; 
     SET roman = SUBSTRING(roman, LENGTH(numeral)); 
    END WHILE; 

    END LOOP the_loop; 
    IF res > 0 THEN 
    RETURN res; 
    ELSE 
    RETURN -1; 
    END IF; 
END$$ 

回答

8

不知道爲什麼你的心不是工作,但谷歌搜索是快,我想出了這個鏈接:

​​

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 
+0

感謝您!這比我寫的更有效率!不知何故,當我以前使用Google搜索功能時,我並沒有將其拉高,但這正是我需要的! – Doug

1

我修改由瓦倫丁提供的功能,使之成爲多一點強大的。

現在: 1)做羅馬數字轉換之前修剪出空白。 2)檢查任何字符傳入的文本不是羅馬數字,並返回,如果是這種情況-1。

這樣的:

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

產量:

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