angularjs римский цифровой эквивалент числа от 1 до 99 [дубликат]

note для пользователей php 7, добавьте это в свой файл httpd.conf:

# PHP 7 specific configuration
<IfModule php7_module>
    AddType application/x-httpd-php .php
    AddType application/x-httpd-php-source .phps
    <IfModule dir_module>
        DirectoryIndex index.html index.php
    </IfModule>
</IfModule>
41
задан Scimonster 27 November 2014 в 16:33
поделиться

32 ответа

Ну, похоже, я не единственный, кто застрял в этой проблеме на FreeCodeCamp. Но я хотел бы поделиться своим кодом с вами в любом случае. Это довольно впечатляюще, почти на 10% быстрее, чем топ-голосованное решение здесь (я не тестировал все остальные, и я думаю, что мой не самый быстрый). Но я думаю, что это чисто и легко понять:

function convertToRoman(num) {
    // Some error checking first
    if (+num > 9999) {
        console.error('Error (fn convertToRoman(num)): Can\'t convert numbers greater than 9999. You provided: ' + num);
        return false;
    }
    if (!+num) {
        console.error('Error (fn convertToRoman(num)): \'num\' must be a number or number in a string. You provided: ' + num);
        return false;
    }

    // Convert the number into
    // an array of the numbers
    var arr = String(+num).split('').map((el) => +el );

    // Keys to the roman numbers
    var keys = {
        1: ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],
        2: ['', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'],
        3: ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'],
        4: ['', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM', 'MMMMMM', 'MMMMMMM', 'MMMMMMMM', 'MMMMMMMMM'],
    };

    // Variables to help building the roman string
    var i = arr.length;
    var roman = '';

    // Iterate over each number in the array and
    // build the string with the corresponding
    // roman numeral
    arr.forEach(function (el) {
        roman += keys[i][el];
        i--;
    });

    // Return the string
    return roman;
}

Это может показаться ограничением, что он может конвертировать только числа до 9 999. Но дело в том, что от 10 000 и выше строка должна быть выше над литералами. И что я еще не решил.

Надеюсь, это вам поможет.

0
ответ дан Adam Bergman 21 August 2018 в 00:45
поделиться

Я не понимаю, почему все решения так длинны и использует несколько циклов.

function convertToRoman(num) {

  var roman =  {"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};
  var str = "";

  for (var i of Object.keys(roman) ) {
    var q = Math.floor(num / roman[i]);
    num -= q * roman[i];
    str += i.repeat(q);
  }

  return str;

}
20
ответ дан August 21 August 2018 в 00:45
поделиться

Я лично считаю, что самый аккуратный способ (а не самый быстрый) - с рекурсией.

function convert(num) { 
  if(num < 1){ return "";}
  if(num >= 40){ return "XL" + convert(num - 40);}
  if(num >= 10){ return "X" + convert(num - 10);}
  if(num >= 9){ return "IX" + convert(num - 9);}
  if(num >= 5){ return "V" + convert(num - 5);}
  if(num >= 4){ return "IV" + convert(num - 4);}
  if(num >= 1){ return "I" + convert(num - 1);}  
}
console.log(convert(39)); 
//Output: XXXIX

Это будет поддерживать только числа 1-40, но его можно легко расширить, следуя шаблону.

1
ответ дан benscabbia 21 August 2018 в 00:45
поделиться

Это работает для всех чисел, которые нуждаются только в римских цифрах M и ниже.

function convert(num) {
  var code = [
    [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"],
  ];

  var rom = "";
  for(var i=0; i<code.length; i++) {
    while(num >= code[i][0]) {
      rom += code[i][1];
      num -= code[i][0];
    }
  }
  return rom;
}
1
ответ дан braham530 21 August 2018 в 00:45
поделиться

Я просто сделал это на freecodecamp. Его можно легко расширить.

function convertToRoman(num) {

  var roman ="";

  var values = [1000,900,500,400,100,90,50,40,10,9,5,4,1];
  var literals = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"];


  for(i=0;i<values.length;i++){
    if(num>=values[i]){
      if(5<=num && num<=8) num -= 5;
      else if(1<=num && num<=3) num -= 1;
      else num -= values[i];
      roman += literals[i];
      i--;
    }
  }


 return roman;
}
2
ответ дан Daniel Arroyo 21 August 2018 в 00:45
поделиться

После тестирования некоторых реализаций в этом сообщении я создал новую оптимизированную для более быстрого выполнения. Исполнение времени действительно низкое по сравнению с другими, но, очевидно, код уродливый :). Это может быть еще быстрее с индексированным массивом со всеми возможностями. На всякий случай это помогает кому-то.

function concatNumLetters(letter, num) {
    var text = "";
    for(var i=0; i<num; i++){
        text += letter;
    }
    return text;
}


function arabicToRomanNumber(arabic) {
    arabic = parseInt(arabic);
    var roman = "";
    if (arabic >= 1000) {
        var thousands = ~~(arabic / 1000);
        roman = concatNumLetters("M", thousands);
        arabic -= thousands * 1000;
    }

     if (arabic >= 900) {
         roman += "CM";
         arabic -= 900;
     }

     if (arabic >= 500) {
         roman += "D";
         arabic -= 500;
     }

     if (arabic >= 400) {
         roman += "CD";
         arabic -= 400;
     }

     if (arabic >= 100) { 
        var hundreds = ~~(arabic / 100);
        roman += concatNumLetters("C", hundreds);
        arabic -= hundreds * 100;
     }

     if (arabic >= 90) {
         roman += "XC";
         arabic -= 90;
     }

     if (arabic >= 50) {
         roman += "L";
         arabic -= 50;
     }

     if (arabic >= 40) {
         roman += "XL";
         arabic -= 40;
     }

     if (arabic >= 10) {
        var dozens = ~~(arabic / 10);
        roman += concatNumLetters("X", dozens);
        arabic -= dozens * 10;
     }

     if (arabic >= 9) {
         roman += "IX";
         arabic -= 9;
     }

      if (arabic >= 5) {
         roman += "V";
         arabic -= 5;
     }

     if (arabic >= 4) {
         roman += "IV";
         arabic -= 4;
     }

     if (arabic >= 1) {
        roman += concatNumLetters("I", arabic);
     }

     return roman;
}
3
ответ дан David Vicente 21 August 2018 в 00:45
поделиться

Я знаю, что это старый вопрос, но я очень горжусь этим решением :) Он обрабатывает номера меньше 1000, но его можно легко расширить, включив в него как можно больший объем, добавив в 2D-код numeralCodes массив.

var numeralCodes = [["","I","II","III","IV","V","VI","VII","VIII","IX"],         // Ones
                    ["","X","XX","XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],   // Tens
                    ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]];        // Hundreds

function convert(num) {
  var numeral = "";
  var digits = num.toString().split('').reverse();
  for (var i=0; i < digits.length; i++){
    numeral = numeralCodes[i][parseInt(digits[i])] + numeral;
  }
  return numeral;  
}
<input id="text-input" type="text">
<button id="convert-button" onClick="var n = parseInt(document.getElementById('text-input').value);document.getElementById('text-output').value = convert(n);">Convert!</button>
<input id="text-output" style="display:block" type="text">

8
ответ дан Deftwun 21 August 2018 в 00:45
поделиться
  • 1
    ясная и элегантная, хорошая работа!: - D – luiyezheng 21 May 2016 в 09:47
  • 2
    Ах, это умно. Я сделал почти то же самое с помощью операторов switch, это было бы моим следующим рефактором после выяснения шаблона и его элегантности. – Jason H 22 July 2016 в 04:46

Я создал два сдвоенных массива, один с арабскими числами, другой с римскими символами.

function convert(num) {

  var result = '';
  var rom = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
  var ara = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];

Затем я добавил цикл, который сканирует римские элементы, добавив, что наибольший по-прежнему состоит из NUM для РЕЗУЛЬТАТОВ, тогда мы уменьшаем NUM той же суммы.

Это похоже на то, что мы отображаем часть NUM в римских числах, а затем уменьшаем ее на ту же сумму.

  for (var x = 0; x < rom.length; x++) {
    while (num >= ara[x]) {
      result += rom[x];
      num -= ara[x];
    }
  }
  return result;
}

2
ответ дан Giorgio Giuliani 21 August 2018 в 00:45
поделиться

Вот решение регулярного выражения:

function deromanize(roman) {
  var r = 0;
  // regular expressions to check if valid Roman Number.
  if (!/^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/.test(roman))
    throw new Error('Invalid Roman Numeral.');

  roman.replace(/[MDLV]|C[MD]?|X[CL]?|I[XV]?/g, function(i) {
    r += {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}[i]; 
  });

  return r;
}
1
ответ дан Gregory R. 21 August 2018 в 00:45
поделиться
function convertToRoman (num) {
    var v = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
    var r = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
    var s = "";
    for(i = 0; i < v.length; i++) {
        value = parseInt(num/v[i]);
        for(j = 0; j < value; j++) {
            s += r[i];
        }
        num = num%v[i];
    }
    return s;
}
1
ответ дан Heting Wu 21 August 2018 в 00:45
поделиться

Мое решение разбивает число на массив строк, добавляет нули к каждому элементу на основе его позиции относительно длины массива, преобразует новые строки с нулями в римские цифры и затем объединяет их вместе. Это будет работать только с номерами до 3999:

function convertToRoman(num){
  var rnumerals = { 1 : 'I', 2 : 'II', 3 : 'III', 4 : 'IV', 5 : 'V', 6   : 'VI', 7 : 'VII', 
  8 : 'VIII', 9 : 'IX', 10 : 'X', 20 : 'XX', 30 : 'XXX', 40 : 'XL', 50 : 'L', 
  60 : 'LX', 70 : 'LXX', 80 : 'LXXX', 90 : 'XC', 100 : 'C', 200 : 'CC', 300 : 'CCC', 
  400 : 'CD', 500 : 'D', 600 : 'DC', 700 : 'DCC', 800 : 'DCCC', 900 : 'CM', 
  1000: 'M', 2000: 'MM', 3000: 'MMM'};

  var zeros, romNum;
  var arr = num.toString().split("");
  var romArr = [];
  for(var i=0; i < arr.length; i++){
    zeros = "0".repeat((arr.length - i - 1));
    arr[i] = arr[i].concat(zeros);
    romArr.push(rnumerals[(arr[i])]); 
  }
  romNum = romArr.join('');
  return romNum;
}
1
ответ дан InfiniteSet 21 August 2018 в 00:45
поделиться
var romanNumerals = [
  ['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]];

RomanNumerals = {
  romerate: function(foo) {
    var bar = '';
    romanNumerals.forEach(function(buzz) {
      while (foo >= buzz[1]) {
        bar += buzz[0];
        foo -= buzz[1]; 
      }
    });
    return bar;
  },
  numerate: function(x) {
    var y = 0;
    romanNumerals.forEach(function(z) {
      while (x.substr(0, z[0].length) == z[0]) {
        x = x.substr(z[0].length);
        y += z[1];
      }
    });
    return y;
  }
};
0
ответ дан Izaak 21 August 2018 в 00:45
поделиться

ЕСЛИ это число в HTMLElement (например, span), мы рекомендуем добавить атрибут HTML data-format:

<p>Phase <span data-format="roman">4 </span> Sales</p>

Примечание. Это не стандарт html. Используемый код Javascript отображается после прокрутки вниз в разделе html на jsfiddle.

DEMO

50
ответ дан jaggedsoft 21 August 2018 в 00:45
поделиться
  • 1
    Это хорошо, кажется, умнее, проще разобрать, что здесь происходит. Начиная с наибольшего числа, продолжайте вычитание из таблицы поиска и добавление до тех пор, пока остаток больше, чем значение поиска. – ac_fire 1 March 2016 в 23:40
  • 2
    Хороший, взял меня на микро секунду, чтобы понять, как насчет сложности – nitansh bareja 27 May 2016 в 17:02
  • 3
    Объекты не имеют порядка! Вы должны использовать массив и избегать for...in. – Oriol 31 July 2016 в 22:01
  • 4
    Я не говорю о производительности. Я говорю, что порядок итераций не гарантируется, поэтому результат может быть совершенно неправильным. – Oriol 2 August 2016 в 00:14
  • 5
    Я не могу дать нерабочий пример, потому что заказ зависит от реализации. Вместо этого, пожалуйста, напишите мне, какая часть спецификации гарантирует, что он будет повторен с желаемым порядком. О, вы не можете . – Oriol 3 August 2016 в 01:35

Если вы хотите преобразовать большое число с большим количеством символов, возможно, этот алго мог бы помочь.

Единственная предпосылка для символов - это то, что должно быть нечетным и следовать одному правилу (1, 5, 10, 50,100 ...., 10 ^ (N) / 2, 10 ^ (N)).

var rnumbers = ["I","V","X","L","C","D","M"];
        rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border-top:1px solid black; padding:1px;">'+n+'</span> '}));
        rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border:1px solid black; border-bottom:1px none black; padding:1px;">'+n+'</span> '}));
        rnumbers = rnumbers.concat(["V","X","L","C","D","M"].map(function(n) {return '<span style="border-top:3px double black; padding:1px;">'+n+'</span> '}));


    String.prototype.repeat = function( num ) {
        return new Array( num + 1 ).join( this );
    };

    function toRoman(n) {

        if(!n) return "";

        var strn = new String(n);
        var strnlength = strn.length;
        var ret = "";
        for(var i = 0 ; i < strnlength; i++) {
            var index = strnlength*2 -2 - i*2;
            var str;
            var m = +strn[i];
            if(index > rnumbers.length -1) {
                str = rnumbers[rnumbers.length-1].repeat(m*Math.pow(10,Math.ceil((index-rnumbers.length)/2)));
            }else {
                str = rnumbers[index].repeat(m);
                if (rnumbers.length >= index + 2) {
                    var rnregexp = rnumbers[index]
                            .split("(").join('\\(')
                            .split(")").join('\\)');
                    
                    str = str.replace(new RegExp('(' + rnregexp + '){9}'), rnumbers[index] + rnumbers[index + 2])
                            .replace(new RegExp('(' + rnregexp + '){5}'), rnumbers[index + 1])
                            .replace(new RegExp('(' + rnregexp + '){4}'), rnumbers[index] + rnumbers[index + 1])
                }
            }
            ret +=str;
        }

        return ret;
    }
    
<input type="text" value="" onkeyup="document.getElementById('result').innerHTML = toRoman(this.value)"/>

<br/><br/>

<div id="result"></div>

2
ответ дан Luca Rainone 21 August 2018 в 00:45
поделиться

Это первый раз, когда я действительно застрял на freecodecamp. Я просмотрел некоторые решения здесь и был поражен тем, насколько они были разными. Вот что для меня работало.

function convertToRoman(num) {
var roman = "";

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

var arrayLen = Object.keys(lookupObj).length;

while(num>0){

 for (i=arrayLen-1 ; i>=0 ; i--){

  if(num >= Object.keys(lookupObj)[i]){

    roman = roman + lookupObj[Object.keys(lookupObj)[i]];        
    num = num - Object.keys(lookupObj)[i];
    break;

  }
 }
}    

return roman;

}

convertToRoman(1231);
1
ответ дан Mogsdad 21 August 2018 в 00:45
поделиться

Эти функции преобразуют любое положительное целое число в его эквивалентную строку Roman Numeral; и любую римскую цифру к ее числу.

Номер в римскую цифру:

Number.prototype.toRoman= function () {
    var num = Math.floor(this), 
        val, s= '', i= 0, 
        v = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1], 
        r = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']; 

    function toBigRoman(n) {
        var ret = '', n1 = '', rem = n;
        while (rem > 1000) {
            var prefix = '', suffix = '', n = rem, s = '' + rem, magnitude = 1;
            while (n > 1000) {
                n /= 1000;
                magnitude *= 1000;
                prefix += '(';
                suffix += ')';
            }
            n1 = Math.floor(n);
            rem = s - (n1 * magnitude);
            ret += prefix + n1.toRoman() + suffix;
        }
        return ret + rem.toRoman();
    }

    if (this - num || num < 1) num = 0;
    if (num > 3999) return toBigRoman(num);

    while (num) {
        val = v[i];
        while (num >= val) {
            num -= val;
            s += r[i];
        }
        ++i;
    }
    return s;
};

Строка римской цифры в номер:

Number.fromRoman = function (roman, accept) {
    var s = roman.toUpperCase().replace(/ +/g, ''), 
        L = s.length, sum = 0, i = 0, next, val, 
        R = { M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1 };

    function fromBigRoman(rn) {
        var n = 0, x, n1, S, rx =/(\(*)([MDCLXVI]+)/g;

        while ((S = rx.exec(rn)) != null) {
            x = S[1].length;
            n1 = Number.fromRoman(S[2])
            if (isNaN(n1)) return NaN;
            if (x) n1 *= Math.pow(1000, x);
            n += n1;
        }
        return n;
    }

    if (/^[MDCLXVI)(]+$/.test(s)) {
        if (s.indexOf('(') == 0) return fromBigRoman(s);

        while (i < L) {
            val = R[s.charAt(i++)];
            next = R[s.charAt(i)] || 0;
            if (next - val > 0) val *= -1;
            sum += val;
        }
        if (accept || sum.toRoman() === s) return sum;
    }
    return NaN;
};
13
ответ дан Onur Yıldırım 21 August 2018 в 00:45
поделиться

Я разработал рекурсивное решение ниже. Функция возвращает одну букву, а затем вызывает себя, чтобы вернуть следующую букву. Он делает это до тех пор, пока число, переданное функции, не будет 0, что означает, что все буквы найдены, и мы можем выйти из рекурсии.

var romanMatrix = [
  [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']
];

function convertToRoman(num) {
  if (num === 0) {
    return '';
  }
  for (var i = 0; i < romanMatrix.length; i++) {
    if (num >= romanMatrix[i][0]) {
      return romanMatrix[i][1] + convertToRoman(num - romanMatrix[i][0]);
    }
  }
}
13
ответ дан Piotr Berebecki 21 August 2018 в 00:45
поделиться
  • 1
    Мне очень нравится ваше решение. Легко читать, понимать и очень просто. Ницца! – Sony ThePony 21 September 2016 в 18:43

В этом блоге есть приятная информация, которую я нашел с помощью google:

http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

function romanize (num) {
    if (!+num)
        return NaN;
    var digits = String(+num).split(""),
        key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM",
               "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC",
               "","I","II","III","IV","V","VI","VII","VIII","IX"],
        roman = "",
        i = 3;
    while (i--)
        roman = (key[+digits.pop() + (i * 10)] || "") + roman;
    return Array(+digits.join("") + 1).join("M") + roman;
}
69
ответ дан Rene Pot 21 August 2018 в 00:45
поделиться
  • 1
    Напоминание: лучше вернуться NaN или бросить вместо возврата false, как обсуждалось в этом сообщении. – Onur Yıldırım 12 October 2015 в 14:59

Эта функция преобразует любое число, меньшее чем 3999999, в римский. Обратите внимание, что числа, превышающие 3999, будут внутри метки с text-decoration, установленными на overline, это добавит overline, которое является правильным представлением для x1000, когда число больше 3999.

Четыре миллиона (4 000 000) будут IV с двумя overline s, поэтому вам нужно будет использовать какой-то трюк, чтобы представить это, возможно, DIV с border-top, или некоторое фоновое изображение с этими двумя overline s .. Каждый overline представляет x1000.

function convert(num){
    num = parseInt(num);

    if (num > 3999999) { alert('Number is too big!'); return false; }
    if (num < 1) { alert('Number is too small!'); return false; }

    var result = '',
        ref = ['M','CM','D','CD','C','XC','L','XL','X','IX','V','IV','I'],
        xis = [1000,900,500,400,100,90,50,40,10,9,5,4,1];

    if (num <= 3999999 && num >= 4000) {
        num += ''; // need to convert to string for .substring()
        result = '<label style="text-decoration: overline;">'+convert(num.substring(0,num.length-3))+'</label>';
        num = num.substring(num.length-3);
    }

    for (x = 0; x < ref.length; x++){
        while(num >= xis[x]){
            result += ref[x];
            num -= xis[x];
        }
    }
    return result;
}
3
ответ дан SeinopSys 21 August 2018 в 00:45
поделиться
  • 1
    Я отредактировал этот код, чтобы число было больше, чем 3,999,999. Это может привести к неверным результатам, поэтому используйте их с осторожностью. jsfiddle.net/DJDavid98/d2VEy – SeinopSys 3 July 2014 в 18:18
  • 2
    Смотрел это .. спасибо !!! – Vamsi Challa 17 June 2015 в 01:53

JavaScript

function romanize (num) {
    if (!+num)
        return false;
    var digits = String(+num).split(""),
        key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM",
               "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC",
               "","I","II","III","IV","V","VI","VII","VIII","IX"],
        roman = "",
        i = 3;
    while (i--)
        roman = (key[+digits.pop() + (i * 10)] || "") + roman;
    return Array(+digits.join("") + 1).join("M") + roman;
}

много других предложений можно найти в http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

4
ответ дан Senad Meškin 21 August 2018 в 00:45
поделиться

Я знаю, что это датированный вопрос, но у меня есть кратчайшее решение тех, которые перечислены здесь, и я думаю, что я поделюсь с тех пор, как я думаю, его легче понять.

Эта версия не требует жесткой кодированной логики для краевых случаев, таких как 4 (IV), 9 (IX), 40 (XL), 900 (CM) и т. д., как это делают другие. Это также означает, что он может обрабатывать большие числа, превышающие 3999, в теории, если применяется правило «не более 3 в строке».

Я тестировал это против 1-3999, и он работает безупречно.

function convertToRoman(num) {
  //create key:value pairs
  var romanLookup = {M:1000, D:500, C:100, L:50, X:10, V:5, I:1};
  var roman = [];
  var romanKeys = Object.keys(romanLookup);
  var curValue;
  var index;
  var count = 1;

  for(var numeral in romanLookup){
    curValue = romanLookup[numeral];
    index = romanKeys.indexOf(numeral);

    while(num >= curValue){

      if(count < 4){
        //push up to 3 of the same numeral
        roman.push(numeral);
      } else {
        //else we had to push four, so we need to convert the numerals 
        //to the next highest denomination "coloring-up in poker speak"

        //Note: We need to check previous index because it might be part of the current number.
        //Example:(9) would attempt (VIIII) so we would need to remove the V as well as the I's
        //otherwise removing just the last three III would be incorrect, because the swap 
        //would give us (VIX) instead of the correct answer (IX)
        if(roman.indexOf(romanKeys[index - 1]) > -1){
          //remove the previous numeral we worked with 
          //and everything after it since we will replace them
          roman.splice(roman.indexOf(romanKeys[index - 1]));
          //push the current numeral and the one that appeared two iterations ago; 
          //think (IX) where we skip (V)
          roman.push(romanKeys[index], romanKeys[index - 2]);
        } else {
          //else Example:(4) would attemt (IIII) so remove three I's and replace with a V 
          //to get the correct answer of (IV)

          //remove the last 3 numerals which are all the same
          roman.splice(-3);
          //push the current numeral and the one that appeared right before it; think (IV)
          roman.push(romanKeys[index], romanKeys[index - 1]);
        }
      }
      //reduce our number by the value we already converted to a numeral
      num -= curValue;
      count++;
    }
    count = 1;
  }
  return roman.join("");
}

convertToRoman(36);
0
ответ дан Shawn 21 August 2018 в 00:45
поделиться
  • 1
    Почему это получило понижение? Это рабочий пример, который отвечает на вопрос и хорошо документирован? – Shawn 9 June 2016 в 21:15
function convertToRoman(num) {

var roNumerals = {
    M: Math.floor(num / 1000),
    CM: Math.floor(num % 1000 / 900),
    D: Math.floor(num % 1000 % 900 / 500),
    CD: Math.floor(num % 1000 % 900 % 500 / 400),
    C: Math.floor(num % 1000 % 900 % 500 % 400 / 100),
    XC: Math.floor(num % 1000 % 900 % 500 % 400 % 100 / 90),
    L: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 / 50),
    XL: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 / 40),
    X: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 / 10),
    IX: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 / 9),
    V: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 / 5),
    IV: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 % 5 / 4),
    I: Math.floor(num % 1000 % 900 % 500 % 400 % 100 % 90 % 50 % 40 % 10 % 9 % 5 % 4 / 1)
  };
  var roNuStr = "";

  for (var prop in roNumerals) {
    for (i = 0; i < roNumerals[prop]; i++) {
      roNuStr += prop;
    }

  }
  return roNuStr;
}

convertToRoman(9);
1
ответ дан Sony ThePony 21 August 2018 в 00:45
поделиться

function convertToRoman(num) {

  var romans = {
    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'
  };
  var popped, rem, roman = '',
    keys = Object.keys(romans);
  while (num > 0) {
    popped = keys.pop();
    m = Math.floor(num / popped);
    num = num % popped;
    console.log('popped:', popped, ' m:', m, ' num:', num, ' roman:', roman);
    while (m-- > 0) {
      roman += romans[popped];
    }
    while (num / popped === 0) {
      popped = keys.pop();
      delete romans[popped];
    }
  }
  return roman;
}
var result = convertToRoman(3999);
console.log(result);
document.getElementById('roman').innerHTML = 'Roman: ' + result;
p {
  color: darkblue;
}
<p>Decimal: 3999</p>
<p id="roman">Roman:</p>

2
ответ дан Srichakradhar 21 August 2018 в 00:45
поделиться
function toRoman(n) {
    var decimals = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
    var roman = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];

    for (var i = 0; i < decimals.length; i++) {
        if(n < 1)
            return "";       

        if(n >= decimals[i]) {
            return roman[i] + toRoman(n - decimals[i]);        
        }
    }
}
1
ответ дан stenou 21 August 2018 в 00:45
поделиться

Если он предназначен только для показа, используйте стандартный HTML с небольшим количеством JS для значения (если необходимо) и CSS, чтобы сделать его inline:

ol.roman-lowercase,
ol.roman-uppercase {
  display: inline-flex;
  margin: 0;
  padding: 0;
}

ol.roman-lowercase {
  list-style: lower-roman inside;
}

ol.roman-uppercase {
  list-style: upper-roman inside;
}
<ol class="roman-lowercase"><li value="4"></li></ol> <!-- iv. -->
<ol class="roman-uppercase"><li value="142"></li></ol> <!-- CXLII. -->

1
ответ дан Tibo 21 August 2018 в 00:45
поделиться
/*my beginner-nooby solution for numbers 1-999 :)*/
function convert(num) {
    var RomNumDig = [['','I','II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'],['X','XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'], ['C','CC','CCC','CD','D','DC','DCC','DCCC','CM']];
    var lastDig = num%10;
    var ourNumb1 = RomNumDig[0][lastDig]||'';
    if(num>=10) {
        var decNum = (num - lastDig)/10;
        if(decNum>9)decNum%=10; 
    var ourNumb2 = RomNumDig[1][decNum-1]||'';} 
    if(num>=100) {
        var hundNum = ((num-num%100)/100);
        var ourNumb3 = RomNumDig[2][hundNum-1]||'';}
return ourNumb3+ourNumb2+ourNumb1;
}
console.log(convert(950));//CML

/*2nd my beginner-nooby solution for numbers 1-10, but it can be easy transformed for larger numbers :)*/
function convert(num) {
  var ourNumb = '';
  var romNumDig = ['I','IV','V','IX','X'];
  var decNum = [1,4,5,9,10];
  for (var i=decNum.length-1; i>0; i--) {
    while(num>=decNum[i]) {
        ourNumb += romNumDig[i];
        num -= decNum[i];
    }
  }
  return ourNumb;
}
console.log(convert(9));//IX
1
ответ дан Vasyl Gutnyk 21 August 2018 в 00:45
поделиться

Эта функция работает с разными наборами символов в каждой цифре. Чтобы добавить еще одну цифру, добавьте римскую цифровую строку: 1 место, 5 место и следующее 1 место. Это хорошо, потому что вы обновляете его, зная только следующий набор символов.

function toRoman(n){
  var d=0,o="",v,k="IVXLCDM".split("");
                    
  while(n!=0){
    v=n%10,x=k[d],y=k[d+1],z=k[d+2];
    o=["",x,x+x,x+x+x,x+y,y,y+x,y+x+x,y+x+x+x,x+z][v]+o;
    n=(n-v)/10,d+=2;
  }
  
  return o
}

var out = "";

for (var i = 0; i < 100; i++) {
  out += toRoman(i) + "\n";
}

document.getElementById("output").innerHTML = out;
<pre id="output"></pre>

1
ответ дан wolfhammer 21 August 2018 в 00:45
поделиться
function convertToRoman(num) {
  var romNumerals = [["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]];
  var runningTotal = 0;
  var roman = "";
  for (var i = 0; i < romNumerals.length; i++) {
    while (runningTotal + romNumerals[i][1] <= num) {
      runningTotal += romNumerals[i][1];
      roman += romNumerals[i][0];
    }
  }

 return roman;
}
1
ответ дан Yup. 21 August 2018 в 00:45
поделиться

Все еще горжусь этим :) Он работает между 1-3999.

var converterArray = [{"1":["I","IV","V","IX"],
                       "2":["X","XL","L","XC"],
                       "3":["C","CD","D","CM"],
                       "4":["M"]}
                     ];

function convertToRoman(num) {
  var romanNumeral = [];
  var numArr = num.toString().split('');
  var numLength = numArr.length;

  for (var i = 0; i<numArr.length; i++) {
    if (numArr[i] < 4) {
      for (var j = 0; j<numArr[i]; j++) {
        romanNumeral.push(converterArray[0][numLength][0]);
      }
    } else if (numArr[i] < 5) {
       for (var j = 3; j<numArr[i]; j++) {
        romanNumeral.push(converterArray[0][numLength][1]);
      }
    } else if (numArr[i] < 9) {
        romanNumeral.push(converterArray[0][numLength][2]);
        for (var j = 5; j<numArr[i]; j++) {
          romanNumeral.push(converterArray[0][numLength][0]);
      }
    } else if (numArr[i] < 10) {
        for (var j = 8; j<numArr[i]; j++) {
          romanNumeral.push(converterArray[0][numLength][3]);
      }
    }
    numLength--;
   }

 return romanNumeral.join('');
}

convertToRoman(9);
1
ответ дан Zsiga 21 August 2018 в 00:45
поделиться
  • 1
    Это путь к большому и сложному – August 21 January 2017 в 22:06
  • 2
    Спасибо за отзывы, вы абсолютно правы! Я сделал это неделю назад, теперь я немного реорганизую его. – Zsiga 23 January 2017 в 15:37
function romanize(num) {
  var lookup = {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},roman = '',i;
  for ( i in lookup ) {
    while ( num >= lookup[i] ) {
      roman += i;
      num -= lookup[i];
    }
  }
  return roman;
}

Отправлено из комментария 2008 года, расположенного по адресу: http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter

VIEW DEMO

50
ответ дан jaggedsoft 21 August 2018 в 00:45
поделиться
  • 1
    Это хорошо, кажется, умнее, проще разобрать, что здесь происходит. Начиная с наибольшего числа, продолжайте вычитание из таблицы поиска и добавление до тех пор, пока остаток больше, чем значение поиска. – ac_fire 1 March 2016 в 23:40
  • 2
    Хороший, взял меня на микро секунду, чтобы понять, как насчет сложности – nitansh bareja 27 May 2016 в 17:02
  • 3
    Объекты не имеют порядка! Вы должны использовать массив и избегать for...in. – Oriol 31 July 2016 в 22:01
  • 4
    Я не говорю о производительности. Я говорю, что порядок итераций не гарантируется, поэтому результат может быть совершенно неправильным. – Oriol 2 August 2016 в 00:14
  • 5
    Я не могу дать нерабочий пример, потому что заказ зависит от реализации. Вместо этого, пожалуйста, напишите мне, какая часть спецификации гарантирует, что он будет повторен с желаемым порядком. О, вы не можете . – Oriol 3 August 2016 в 01:35
Другие вопросы по тегам:

Похожие вопросы: