在JavaScript中将数字转换为罗马数字

96

我该如何将整数转换为罗马数字

function romanNumeralGenerator (int) {

}
例如,看下面的样例输入和输出:
1 = "I"
5 = "V"
10 = "X"
20 = "XX"
3999 = "MMMCMXCIX"

注意:仅支持1到3999之间的数字。

96个回答

0

这是我的解决方案,我不太确定它的性能如何。

function convertToRoman(num) {

  var uni = ["","I","II","III","IV","V","VI","VII","VIII","IX"];
  var dec = ["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"];
  var cen = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"];
  var mil = ["","M","MM","MMM","MMMM","MMMMM","MMMMMM","MMMMMMM","MMMMMMMM","MMMMMMMMMM"];

  var res =[];

  if(num/1000 > 0)
    {
      res = res.concat(mil[Math.floor(num/1000)]);
    }

  if(num/100 > 0)
    {
      res = res.concat(cen[Math.floor((num%1000)/100)]);
    }

  if(num/10 >0)
    {
      res = res.concat(dec[Math.floor(((num%1000)%100)/10)]);
    }

  res=res.concat(uni[Math.floor(((num%1000)%100)%10)]);

  return res.join('');
}

0
function toRoman(n) {
        var r = '';
        for (var c = 0; c < n.length; c++)
            r += calcDigit(eval(n.charAt(c)), n.length - c - 1);
        return r
    }

function Level(i, v, x) {
    this.i = i;
    this.v = v;
    this.x = x
}

levels = [];
levels[0] = new Level('I','V','X');
levels[1] = new Level('X','L','C');
levels[2] = new Level('C','D','M');

function calcDigit(d, l) {
    if (l > 2) {
        var str = '';
        for (var m = 1; m <= d * Math.pow(10, l - 3); m++)
            str += 'M';
        return str
    } else if (d == 1)
        return levels[l].i;
    else if (d == 2)
        return levels[l].i + levels[l].i;
    else if (d == 3)
        return levels[l].i + levels[l].i + levels[l].i;
    else if (d == 4)
        return levels[l].i + levels[l].v;
    else if (d == 5)
        return levels[l].v;
    else if (d == 6)
        return levels[l].v + levels[l].i;
    else if (d == 7)
        return levels[l].v + levels[l].i + levels[l].i;
    else if (d == 8)
        return levels[l].v + levels[l].i + levels[l].i + levels[l].i;
    else if (d == 9)
        return levels[l].i + levels[l].x;
    else
        return ''
}

0

我只是发布了一个将数字转换为罗马数字的函数,希望你喜欢它。

function converter(numToConv) {
var numToRom = [];
var numToRome = "";
var R = [['M',1000], ['D',500], ['C',100], ['L',50], ['X',10], ['V',5], ['I',1]];
while (numToConv > 0) {
    if (numToConv > R[0][1]) {
        if (numToConv < R[0][1] * 5 - R[0][1]) {   
            numToRom.push([R[0][0],"next one goes aftah"]);
            numToConv = Math.abs(numToConv - R[0][1]);
            console.log("Next comes after: " + R[0][0] + " (" + R[0][1] + ")");
            console.log(numToConv);
        } else {
            numToConv = 0;
            break;
        }
    }
    for (var i = 0; i < R.length; i++) {
        if (R[i][1] == numToConv) {
            numToRom.push([R[i][0],"end"]);
            numToConv = Math.abs(numToConv - R[i][1]);
            console.log("End: " + numToConv);
        } else if (i > 0) {
            if ((R[i-1][1] > numToConv) && (R[i][1] < numToConv)) {
                console.log(numToConv + " is between: " + R[i][1]  + " (" + R[i][0] + ") and: " +  R[i - 1][1]  + " (" + R[i - 1][0] + ")");
                var threshold = R[i - 1][1] - Math.pow(10, numToConv.toString().length - 1);
                console.log("threshold: " + threshold + " : " + R[i][1] + " : " + Math.pow(10, numToConv.toString().length - 1));
                if (numToConv  < threshold) {
                    numToRom.push([R[i][0],"next one goes aftah"]);
                    numToConv = Math.abs(numToConv - R[i][1]);
                    console.log("Next comes after: " + R[i][0] + " (" + R[i][1] + ")");
                    console.log(numToConv);
                } else {
                    numToRom.push([R[i-1][0],"next one goes befoah"]);
                    numToConv = Math.abs(numToConv - threshold + Math.pow(10, numToConv.toString().length - 1));
                    console.log("Next comes before: " + R[i-1][0] + " (" + R[i-1][1] + ")");
                    console.log(numToConv);
                }
            }
        }
    }
}
console.log("numToRom: " + numToRom);
for (var i = 0; i < numToRom.length; i++) {
    if (numToRom[i][1] == "next one goes befoah") {
        numToRome += (numToRom[i+1][0] + numToRom[i][0]);
        console.log("numToRome goes befoah: " + numToRome + " i: " + i);
        i++;
    } else {
        numToRome += numToRom[i][0];
        console.log("numToRome goes aftah: " + numToRome + " i: " + i);
    }
}
        console.log("numToRome: " + numToRome);
        return numToRome;

}

带有注释的编辑代码:

function converter(numToConv) {
    var numToRom = []; //an array empty, ready to store information about the numbers we will use as we analyse the given number 
    var numToRome = ""; // this is a string to add the Roman letters forming our returning number
    var R = [['M',1000], ['D',500], ['C',100], ['L',50], ['X',10], ['V',5], ['I',1]]; //this array stores the matches with the arabic numbers that we are going to need
    while (numToConv > 0) { //just checking, there is no zero
        if (numToConv > R[0][1]) { //checks if the number is bigger than the bigger number in the array
            if (numToConv < R[0][1] * 5 - R[0][1]) { //checks if it is larger even than 4 times the larger number in the array (just because there is not usually a way to express a number by putting 4 times the same letter i.e there is no "IIII", or "XXXX" etc)
                numToRom.push([R[0][0],"next one goes aftah"]);//here is the information we want to pass, we add the letter we are about to use along with info about the next letter
                numToConv = Math.abs(numToConv - R[0][1]);// and now we are subtracting the value of the letter we are using from the number
                console.log("Next comes after: " + R[0][0] + " (" + R[0][1] + ")");// informing about what we encountering
                console.log(numToConv);//..as well as what's the next number
            } else { //if the number is larger than 4 times the larger number in the array (thus it cannot be expressed)
                numToConv = 0; //then 0 the number (unnecessary but still, no problem doing it)
                break;//and of course, breaking the loop, no need to continue
            }
        }
        for (var i = 0; i < R.length; i++) {//now we are about to search our number for each cell of the array with the roman letters (again and again)
            if (R[i][1] == numToConv) { //if the number is equal to the one in the cell (that means the conversion is over)
                numToRom.push([R[i][0],"end"]); //we pass the information about that cell along with the indication that the conversion has ended
                numToConv = Math.abs(numToConv - R[i][1]);//thai can also be skipped but again there is o harm in keeping it
                console.log("End: " + numToConv);// again informing about what we encountering
            } else if (i > 0) { //just a precaution because we are about to use "i-1" 
                if ((R[i-1][1] > numToConv) && (R[i][1] < numToConv)) {//we find the range in which is the given number (for instance: the number 4 is between 1[I] and 5[V])
                    console.log(numToConv + " is between: " + R[i][1]  + " (" + R[i][0] + ") and: " +  R[i - 1][1]  + " (" + R[i - 1][0] + ")");// once again informing
                    var threshold = R[i - 1][1] - Math.pow(10, numToConv.toString().length - 1);// we create this "threshold" to check if the next number is going before or after this one (difference between 7[VII] and 9[IX]). it is the larger number of our range - 10^[depends on how large is the number we want to convert] (for 999, the threshold is 900, it is smaller 1000 - 10^2)
                    console.log("threshold: " + threshold + " : " + numToConv + " : " + R[i - 1][1] + " : " + R[i][1] + " : " + Math.pow(10, numToConv.toString().length - 1));
                    if (numToConv  < threshold) {//if the number is smaller than the "threshold" (like 199 where its threshold is 400)
                        numToRom.push([R[i][0],"next one goes aftah"]);//then the next number is going after
                        numToConv = Math.abs(numToConv - R[i][1]);//and again, subtract the used value of the number we are converting
                        console.log("Next comes after: " + R[i][0] + " (" + R[i][1] + ")");
                        console.log(numToConv);
                    } else { // now, if the number is larger than the threshold (like 99 where its threshold is 90)
                        numToRom.push([R[i-1][0],"next one goes befoah"]);// then the next number is going before the one we add now
                        numToConv = Math.abs(numToConv - R[i - 1][1]);// again, the subtraction, it was "threshold + Math.pow(10, numToConv.toString().length - 1)" but I changed it to "R[i - 1][1]", same result, less operations
                        console.log("Next comes before: " + R[i-1][0] + " (" + R[i-1][1] + ")");
                        console.log(numToConv);
                    }
                }
            }
        }
    }
    console.log("numToRom: " + numToRom); //now that we have all the info we need about the number, show it to the log (just for a check)
    for (var i = 0; i < numToRom.length; i++) {//..and we start running through that info to create our final number
        if (numToRom[i][1] == "next one goes befoah") {//if our information about the cell tells us that the next letter is going before the current one
            numToRome += (numToRom[i+1][0] + numToRom[i][0]);// we add both to our string (the next one first)
            console.log("numToRome goes befoah: " + numToRome + " i: " + i);
            i++;//and we add an extra '1' to the i, so it will skip the next letter (mind that there won't be more than one letters saying that the next one is going before them in a row
        } else {//if the next one is going after the current one
            numToRome += numToRom[i][0]; //we just add the one we are on to the string and go forth
            console.log("numToRome goes aftah: " + numToRome + " i: " + i);
        }
    }
            console.log("numToRome: " + numToRome);
            return numToRome;//return the string and we are done
}

代码的解释会提高答案的价值。 - Aminah Nuraini
1
你刚刚发布了jQuery库的副本吗?我花了一段时间才读懂这个,也许需要简化一下。 - Sony ThePony
抱歉,各位,我刚看到你们的评论。我会尽快给代码加上注释。 - Orestes Kyriakos Poulakis
做完了,我加了一些注释(虽然我担心有点过头了) - Orestes Kyriakos Poulakis

0
function convertToRoman(num) {

  var search = {
    "0":["I","II","III","IV","V","VI","VII","VIII","IX"],
    "1":["X","XX","XXX","XL","L","LX","LXX","LXXX","XC"],
    "2":["C","CC","CCC","CD","D","DC","DCC","DCCC","CM"],
    "3":["M","MM","MMM","MV^","V^","V^M","V^MM","V^MMM","MX^"],
  };

  var numArr = num.toString().split("").reverse();
  var romanReturn = [];
  for(var i=0; i<numArr.length; i++){
    romanReturn.unshift(search[i][numArr[i]-1]);
  }
  return romanReturn.join("");
}

0
let converter={
 I : 1, II: 2, III:3, IV:4, V:5, VI:6, VII:7, VIII:8, IX:9
 }
 let converter1={
    X:10,XX:20,XXX:30,XL:40,L:50,LX:60,LXX:70,LXXX:80,XC:90
 }
 let converter2={
    C:100,CC:200,CCC:300,CD:400,D:500,DC:600,DCC:700,DCCC:800,CM:900
 }

    let result= []
  function convertToRoman(number){

        if(number >= 1000){
                  let l = 'M'
                  result.push(l.repeat(number/1000))
                    if(number%1000  < 1000){
                    number = number%1000
                  }
                }
           if(100 <=number && number <= 999){
                      let border = String(number)[0]
                      for(let i=0; i <= Number(border); i++){
                        if(Object.values(converter2)[i]/ Number(border) == 100){
                          result.push(Object.keys(converter2)[i])
                          number = number-Object.values(converter2)[i]

                        }
                        }
                    }
    if(10 <= number && number <= 99){

                      let border= String(number)[0]

                      for(let i = 0; i < Number(border) ; i++){
                        if(Object.values(converter1)[i]===  Number(border)*10  ){
                          result.push(Object.keys(converter1)[i])
                            number = number-Object.values(converter1)[i]
                          }
                        }
                }

    if(number <= 9){
                    for(let i = 0; i <= number; i++){
                      if(Object.values(converter)[i] == number){
                        result.push(Object.keys(converter)[i])
                        result = result.join("")
                          result = String(result)
                        return result
                            }
                                }
                    }
                    result = result.join("")
                      result = String(result)
                    return result
                }


console.log(convertToRoman(9))

0

我觉得这个解决方案可能会帮助你更好地理解问题

const romanNumeral = function (num) {
let roman = "";
let nums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
let romans = [
"M",
"CM",
"D",
"CD",
"C",
"XC",
"L",
"XL",
"X",
"IX",
"V",
"IV",
"I",
];
for (let i = 0; i < nums.length; i++) {
while (num >= nums[i]) {
  roman += romans[i];
  num -= nums[i];
}
return roman;
};

目前您的回答不够清晰。请[编辑]以添加更多细节,帮助其他人了解这如何解决所问的问题。您可以在帮助中心找到更多编写良好答案的信息。 - Community

0
以简单的方式来说 -
function convertToRoman (num) {
  const romanList = {
    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
  }
  let roman = "";
  Object.keys(romanList).forEach((key, index) => {
      let temp = parseInt(num / romanList[key]);
      num = num % romanList[key];
      roman = roman + key.repeat(temp);
  });

  return roman;
};

0

没有看到矩阵数组与 for 循环和嵌套三目运算符一起使用,看起来很花哨,但它几乎没有超出硬编码区域,希望你喜欢。

function rome(num) {
  if (num > 3999) {return 'number too large'};
  let strNum = JSON.stringify(num).split("");
  let number = [];
  let romans = [ ['I','IV','V','IX'],
                 ['X','XL','L','XC'],
                 ['C','CD','D','CM'],
                 ['M','','','']      ]; 
  for (let j = strNum.length - 1 ; 0 <= j; j--){
      let digit ='';
      digit = strNum[j] == 0 ?  '' : 
              strNum[j] <= 3 ? 
              romans[strNum.length-1-j][0].repeat(Number(strNum[j])) :
              strNum[j] == 4 ? romans[strNum.length-1-j][1] : 
              strNum[j] == 5 ? romans[strNum.length-1-j][2] :
              strNum[j] <= 8 ? romans[strNum.length-1-j][2] + 
              romans[strNum.length-1-j][0].repeat(Number(strNum[j])-5) : 
              romans[strNum.length-1-j][3] ;
      number.unshift(digit);
      };
  return ''.concat(number.join(''));
 }

0
我想出了这个解决方案:
function toRoman(str) {
    const g = [
        ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
        ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'LC'],
        ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'],
        ['', 'M', 'MM', 'MMM','MMMM','V\u0305','V\u0305M','V\u0305MM','V\u0305MMM','MX\u0305']
    ]
    a = str.toString()
    console.assert(a.length < 5, 'Number must be less than 10000 was %o', {a});
    return isNaN(a) ? NaN : [...a].map((s, i) => g[a.length - i - 1][s]).join("")
}

特点:

  1. 它使用高效的扩展运算符来迭代字符串。
  2. 适用于1到9999之间的数字。
  3. 如果不是数字,则返回NaN。
  4. 如果数字大于9999,则抛出错误。
  5. 仅有XI行代码。

0
function convertToRoman(num: number){
  let integerToRomanMap = new Map<number, string>([
    [1000, "M"], [900, "CM"], [800, "DCCC"], [700, "DCC"], [600, "DC"],
    [500, "D"], [400, "CD"], [300, "CCC"], [200, "CC"], 
    [100, "C"], [90, "XC"], [80, "LXXX"], [70, "LXX"], [60, "LX"], 
    [50, "L"], [40, "XL"], [30, "XXX"], [20, "XX"], 
    [10, "X"], [9, "IX"], [8, "VIII"], [7, "VII"], [6, "VI"], 
    [5, "V"], [4, "IV"], [3, "III"], [2, "II"], [1, "I"]
  ])
  if(integerToRomanMap.has(num)){
    return integerToRomanMap.get(num)
  }
  let res = ''
  while(num > 0){
    let len = String(num).length;
    let divisor = Math.pow(10, len - 1)
    let quotient = Math.floor(num/divisor)
    num = num % divisor
    if(integerToRomanMap.has(divisor * quotient)){
      res += integerToRomanMap.get(divisor * quotient)
    }else{
      while(quotient > 0){
        res += integerToRomanMap.get(divisor)
        quotient--;
      }
    }
  }
  return res;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接