{"id":412,"date":"2009-03-09T12:48:01","date_gmt":"2009-03-09T18:48:01","guid":{"rendered":"http:\/\/bililite.nfshost.com\/blog\/?p=412"},"modified":"2013-07-31T13:58:28","modified_gmt":"2013-07-31T19:58:28","slug":"roman-numerals-in-javascript","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2009\/03\/09\/roman-numerals-in-javascript\/","title":{"rendered":"Roman Numerals in Javascript"},"content":{"rendered":"<p>I was looking at some code that included converting arabic to roman numerals, and it was all things like <a href=\"http:\/\/www.novaroma.org\/via_romana\/numbers.html\">this<\/a>:<\/p>\r\n<!--more-->\r\n<pre><code class=\"language-javascript\">\r\nfunction Level(i, v, x)\r\n        {\r\n        this.i = i;\r\n        this.v = v;\r\n        this.x = x\r\n        }\r\n\r\nlevels = new Array();\r\n\r\nlevels[0] = new Level('I', 'V', 'X');\r\nlevels[1] = new Level('X', 'L', 'C');\r\nlevels[2] = new Level('C', 'D', 'M');\r\n\r\nfunction calcDigit(d, l)\r\n        {\r\n        if (l > 2)\r\n                {\r\n                str = '';\r\n                for (var m = 1; m <= d * Math.pow(10, l - 3) ; m++)\r\n                        str += 'M';\r\n                return str\r\n                }\r\n                        \r\n        else\r\n                if (d == 1)\r\n                        return levels[l].i\r\n                else\r\n                        if (d == 2)\r\n                                return levels[l].i + levels[l].i\r\n                        else\r\n                                if (d == 3)\r\n                                        return levels[l].i + levels[l].i + levels[l].i\r\n                                else\r\n                                        if (d == 4)\r\n                                                return levels[l].i + levels[l].v\r\n                                        else\r\n                                                if (d == 5)\r\n                                                        return levels[l].v\r\n                                                else\r\n                                                        if (d == 6)\r\n                                                                return levels[l].v + levels[l].i\r\n                                                        else\r\n                                                                if (d == 7)\r\n                                                                        return levels[l].v + levels[l].i + levels[l].i\r\n                                                                else\r\n                                                                        if (d == 8)\r\n                                                                                return levels[l].v + levels[l].i + levels[l].i + levels[l].i\r\n                                                                        else\r\n                                                                                if (d == 9)\r\n                                                                                        return levels[l].i + levels[l].x\r\n                                                                                else\r\n                                                                                        return ''\r\n\/\/ And so on\r\n<\/code><\/pre>\r\n<p>It all reminded me of fourth-grade BASIC. I should have been taking care of patients, but the challenge of writing a better converter kept me busy for a few minutes. Here's what I came up with:<\/p>\r\n<pre><code class=\"language-javascript demo\">\r\nvar romanNumerals = [\r\n\t[1000, 'M'],\r\n\t[900, 'CM'],\r\n\t[500, 'D'],\r\n\t[400, 'CD'],\r\n\t[100, 'C'],\r\n\t[90, 'XC'],\r\n\t[50, 'L'],\r\n\t[40, 'XL'],\r\n\t[10, 'X'],\r\n\t[9, 'IX'],\r\n\t[5, 'V'],\r\n\t[4, 'IV'],\r\n\t[1, 'I']\r\n];\r\narabic2roman = function(n){\r\n\tvar r = '';\r\n\tfor (var i = 0; i < romanNumerals.length; ++i){\r\n\t\tfor (var x = romanNumerals[i]; n >= x[0]; n -= x[0]) r += x[1];\r\n\t}\r\n\treturn r;\r\n}\r\nroman2arabic = function(r){\r\n\tvar n = 0;\r\n\tfor (var i = 0; i < romanNumerals.length; ++i){\r\n\t\tfor (var x = romanNumerals[i], l = x[1].length; r.substr(0,l) == x[1]; r = r.substr(l)) n += x[0];\r\n\t}\r\n\treturn n;\r\n}\r\n<\/code><\/pre>\r\n<form><input id=\"source\"\/><input type=\"submit\" value=\"Convert\"\/> <span id=\"result\"><\/span><\/form>\r\n<script>\r\n$('#source').parent().submit(function(e){\r\n  e.preventDefault();\r\n  var text = $('#source').val();\r\n  if (\/\\d\/.test(text)) $('#result').text(arabic2roman(text));\r\n  else $('#result').text(roman2arabic(text.toUpperCase()));\r\n});\r\n<\/script>\r\n<p>Or, if you are willing to assume that your browser will always <a href=\"http:\/\/ejohn.org\/blog\/javascript-in-chrome\/\">enumerate objects in order<\/a>, you can make it a bit smaller:<\/p>\r\n<pre><code class=\"language-javascript\">\r\nvar romanNumerals = { \/\/ assumes objects are enumerated in order\r\n\tM: 1000,\r\n\tCM: 900,\r\n\tD: 500,\r\n\tCD: 400,\r\n\tC: 100,\r\n\tXC: 90,\r\n\tL: 50,\r\n\tXL: 40,\r\n\tX: 10,\r\n\tIX: 9,\r\n\tV: 5,\r\n\tIV: 4,\r\n\tI: 1\r\n};\r\narabic2roman = function(n){\r\n\tvar r = '';\r\n\tfor (var x in romanNumerals){\r\n\t\tfor (var i = romanNumerals[x]; n >= i; n -= i) r += x;\r\n\t}\r\n\treturn r;\r\n}\r\nroman2arabic = function(r){\r\n\tvar n = 0, i = 0;\r\n\tfor (var x in romanNumerals){\r\n\t\tfor (var l = x.length; r.substr(i,l) == x; i+=l) n += romanNumerals[x];\r\n\t}\r\n\treturn n;\r\n}\r\n<\/code><\/pre>\r\n<p>Anyone out there with something smaller?<\/p>\r\n<p>Edit 2013-07-31: this code is licensed under the <a href=\"http:\/\/opensource.org\/licenses\/MIT\">MIT open source license<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"I was looking at some code that included converting arabic to roman numerals, and it was all things like this:","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/412"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=412"}],"version-history":[{"count":11,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/412\/revisions"}],"predecessor-version":[{"id":2921,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/412\/revisions\/2921"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=412"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=412"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=412"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}