在某些情况下,Roman to Int转换错误

时间:2016-09-25 08:38:28

标签: javascript roman-numerals

我的功能如下:

let romanToInt = romanNumber => {
    if(typeof romanNumber !== 'string') throw new TypeError('Argument must be of type String');

    const values = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 };
    let sum = 0;

    romanNumber.split('').map(n => n.toUpperCase()).forEach(n => sum = (sum >= values[n]) ? sum + values[n] : values[n] - sum);

    return sum;
}

console.log(romanToInt("MCMXCVI"));

我测试的大部分输入都是正确的,但罗马数字MCMXCVI例如应该给我1996,而不是2216,这就是我得到的。

我发现了这一点,但我不确定如何实现:

  

您必须将数十,数百和数千个单独分开   项目。这意味着99是XCIX,90 + 9,但永远不应该写   作为IC。同样,999不能是IM而1999不能是MIM。

3 个答案:

答案 0 :(得分:1)

根据您的问题,您需要迎合单独的项目。一种简单的方法是简单地将您的值设置得更大,并寻找多字符匹配。这是可能的,因为只有少数组合允许使用罗马数字。我把小提琴放在一起here

const values = { 
  'I': 1, 
  'V': 5, 
  'X': 10, 
  'L': 50, 
  'C': 100, 
  'D': 500, 
  'M': 1000,
  'CM': 900,
  'CD': 400,
  'XC': 90,
  'XL': 40,
  'IX': 9,
  'IV': 4
};

let sum = 0;

while(romanNumber.length > 0){
  let piece = romanNumber.substring(0,2);
  if(values[piece]){
    sum += values[piece];
    romanNumber = romanNumber.substring(2);
  }else if(values[piece[0]]){
    sum += values[piece[0]];
    romanNumber = romanNumber.substring(1);
  }
}

return sum;

答案 1 :(得分:0)

您不应该希望通过简单的映射来解决问题,因为在罗马数字中,数字的含义取决于上下文。我认为,许多情况可以用类似的东西来处理(而不是你的分裂和地图行):

var digits = romanNumber.split('');
var i = 0;
while (i < digits.length) {
    if (i == digits.length - 1 || values[digits[i]] >= values[digits[i+1]]) {
        sum += values[digits[i]];
        i++;
    }
    else {
        sum += values[digits[i+1]] - values[digits[i]];
        i += 2;
    }
}

但我不确定它是否适用于所有情况。最好看看它是如何在现成的库中实现的,也许是为其他语言实现的。例如,以下是Perl的实现:http://search.cpan.org/~chorny/Roman-1.24/lib/Roman.pm

答案 2 :(得分:0)

我认为你不能用单线程映射来实现,因为操作取决于彼此相邻的字符比较。但是,使用简单的for循环:

var chars = romanNumber.split('');
var sum = values[chars[chars.length - 1]];
for (var i = chars.length - 2; i >= 0; i--) {
    if (values[chars[i + 1]] <= values[chars[i]]) {
        sum += values[chars[i]];
    } else {
        sum -= values[chars[i]];
    }
}

当罗马数字的值小于其右边的数字时,你想要从总和中减去它而不是添加。