Roman Numerals Conversions

$$ \newcount\tmpnum \newdimen\tmpdim {\lccode`\?=`\p \lccode`\!=`\t \lowercase{\gdef\ignorept#1?!{#1}}} \edef\widecharS{\expandafter\ignorept\the\fontdimen1\textfont1} \def\widebar#1{\futurelet\next\widebarA#1\widebarA} \def\widebarA#1\widebarA{% \def\tmp{0}\ifcat\noexpand\next A\def\tmp{1}\fi \widebarE \ifdim\tmp pt=0pt \overline{#1}% \else {\mathpalette\widebarB{#1}}\fi } \def\widebarB#1#2{% \setbox0=\hbox{$#1\overline{#2}$}% \tmpdim=\tmp\ht0 \advance\tmpdim by-.4pt \tmpdim=\widecharS\tmpdim \kern\tmpdim\overline{\kern-\tmpdim#2}% } \def\widebarC#1#2 {\ifx#1\end \else \ifx#1\next\def\tmp{#2}\widebarD \else\expandafter\expandafter\expandafter\widebarC \fi\fi } \def\widebarD#1\end. {\fi\fi} \def\widebarE{\widebarC A1.4 J1.2 L.6 O.8 T.5 U.7 V.3 W.1 Y.2 a.5 b.2 d1.1 h.5 i.5 k.5 l.3 m.4 n.4 o.6 p.4 r.5 t.4 v.7 w.7 x.8 y.8 \alpha1 \beta1 \gamma.6 \delta.8 \epsilon.8 \varepsilon.8 \zeta.6 \eta.4 \theta.8 \vartheta.8 \iota.5 \kappa.8 \lambda.5 \mu1 \nu.5 \xi.7 \pi.6 \varpi.9 \rho1 \varrho1 \sigma.7 \varsigma.7 \tau.6 \upsilon.7 \phi1 \varphi.6 \chi.7 \psi1 \omega.5 \cal1 \end. } $$

Test page for Roman numeral conversions. Up to 899, all forms of RN are equivalent, but starting at 900, divergences appear. In standard numerals (ASRN), 1000 is M, as well as in Extended numerals (ERN). In Lowercase-extended numerals (LRN), i is obtained, while in "Compatible" numerals (CRN), 1000 is written as (I). This is the smallest example of the main extension I have made to the roman numerals, in which, once the available symbols are exhausted, parentheses are added around them to multiply by the 10x largest 10-symbol (I, X, C, and M are the standard "10-symbols"). (This is an imitation of the "vinculum" used by people with access to more than ASCII, and there is also a "TeXify" script included in the source files that will (poorly) convert the parentheses into overlines using TeX. (or TeX, if you enjoy formatting)) The converter does this in a very simple way, whereby (I) is treated as a separate symbol, so in CRN 2000 "should be" (I)(I), but the "minify" script removes the superfluous parentheses. This process does not occur for absolutely standard numerals (ARN), and instead it simply adds additional M's. This is limited to 99 consecutive M's (99 000), after which point it is abbreviated as in M[*100]. (At 99 900, there are a total of 100 M's, the last one being subtracted from. This is the maximal number of M's possible.) This preserves the logarithmic nature of "positional" numerals. (If you think about it, RN with subtraction is "positional", but not in the same way as decimal. In any case, any form of infinitely-extensible RN (ERN, LRN, CRN) is logarithmic.)

(A previous version would also convert the abbreviated number into ARN recursively, which meant that for astronomically (or combinatorially) large numbers, there would be a double abbreviation, like M[*M[*100]]. This was removed because it got out of hand and was very hard to read.)

Otherwise, the only differences between the different types of RN available are the sets of symbols. In CRN, the symbols are [IVXLCD], with M being accepted as (I). In LRN, it is [IVXLCDivxlcd]. M is accepted but m is not. In ERN, it is [IVXLCDMABEFGHJKNOPQRSTUWYZ], which is simply the standard set followed by the remainder of the alphabet in order. I decided that another lowercase set probably wasn't worthwhile, so ZZ is (I) and not i.

The parser is fully-featured save for the M[*number] abbreviation used for ARN output, but I can conceive of no reason why you would ever need to convert numbers greater than 99 999 into Roman numerals and not be able to use any extensions at all. It is also a partial implementation of an RPN five-function (modulus, not exponentiation) calculator for big integers, but there are much better such calculators available so that functionality is not exposed by the web interface.

If you wish to download the program yourself, or are merely curious about the strange codewords appearing in the invocation in the text box, I will have to describe the interface for the program. Technical details aside, t is used to convert decimal numbers to various types of Roman numerals (switching on the second character of the codeword), f for the inverse, and c for canonization/simplification, that is, transforming RN into the equivalent that follows all of these rules:

In fact, none of these rules are explicitly stated in the code, because it turns out they're all consequences of a different rule:

That is to say, in 900, 9 maps to IX, and then IX is "shifted" to the correct place value, yielding CM. The only snag is that, in ARN, there are only a finite number of possible symbols, so instead the number is first divided by 1000 and that number of M's is printed, limited as described above. By default, Roman will run in "interactive mode", reading commands one at a time and executing them every new line. A command is written as "<abbreviated function name> arguments", and a full list of them is available by running "= p p-", using the "apply" function, "=". = takes the names of two functions and an optional list of arguments. The list of arguments is given to the second function, and the output of that to the first. p (and the related p-) are used to examine the list of available commands, which is stored as a trie.

If you've read all that, then I should probably give you a link to the source directory, here made available under the terms of the 3-clause BSD license.


\(\mbox{Commands include the following: \(\overline{\mbox{Abbreviate to capital letters}}\) Echo \(\overline{\mbox{string...}}\), eXecute \(\overline{\mbox{command \(\overline{\mbox{args...}}\)}}\), Probe trie \(\overline{\mbox{command}}\), Help \(\overline{\mbox{command}}\), Quit, To \(\overline{\mbox{extended/Compatible/Lowercase-extended/Absolutely standard}}\) roman \(\overline{\mbox{number}}\), From \(\overline{\mbox{extended/Compatible/Lowercase-extended/ Absolutely standard}}\) roman \(\overline{\mbox{numeral}}\), Canonicize \(\overline{\mbox{e/C/L/A}}\) \(\overline{\mbox{numeral}}\) Input is accepted as "e test test2" For a complete list, run "= p p-". }\)

Utility Functions: Clear; Duplicate