Roman numerals/Encode: Difference between revisions

m
→‎{{header|Phix}}: use pygments, added cheat version
m (→‎version 2: capitalized "bif", added whitespace to the programming comment. -- ~~~~)
m (→‎{{header|Phix}}: use pygments, added cheat version)
 
(307 intermediate revisions by more than 100 users not shown)
Line 1:
{{task}}
[[Category:String_manipulation]]
Create a function taking a positive integer as its parameter and returning a string containing the Roman Numeral representation of that integer.
{{omit from|GUISS}}
 
;Task:
Modern Roman numerals are written by expressing each digit separately starting with the left most digit and skipping any digit with a value of zero. In Roman numerals 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC. 2008 is written as 2000=MM, 8=VIII; or MMVIII. 1666 uses each Roman symbol in descending order: MDCLXVI.
Create a function taking a positive integer as its parameter and returning a string containing the Roman numeral representation of that integer. Modern Roman numerals are written by expressing each digit separately, starting with the left most digit and skipping any digit with a value of zero.
 
 
In Roman numerals:
* 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC
* 2008 is written as 2000=MM, 8=VIII; or MMVIII
* 1666 uses each Roman symbol in descending order: MDCLXVI
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">V anums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
V rnums = ‘M CM D CD C XC L XL X IX V IV I’.split(‘ ’)
 
F to_roman(=x)
V ret = ‘’
L(a, r) zip(:anums, :rnums)
(V n, x) = divmod(x, a)
ret ‘’= r * n
R ret
 
V test = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30, 40,
50, 60, 69, 70, 80, 90, 99, 100, 200, 300, 400, 500, 600, 666, 700, 800, 900, 1000,
1009, 1444, 1666, 1945, 1997, 1999, 2000, 2008, 2010, 2011, 2500, 3000, 3999]
L(val) test
print(val‘ - ’to_roman(val))</syntaxhighlight>
 
=={{header|360 Assembly}}==
<syntaxhighlight lang="360asm">* Roman numerals Encode - 11/05/2020
ROMAENC CSECT
USING ROMAENC,R13 base register
B 72(R15) skip savearea
DC 17F'0' savearea
SAVE (14,12) save previous context
ST R13,4(R15) link backward
ST R15,8(R13) link forward
LR R13,R15 set addressability
LA R6,1 i=1
DO WHILE=(C,R6,LE,=A(8)) do i=1 to hbound(nums)
LR R1,R6 i
SLA R1,1 ~
LH R8,NUMS-2(R1) n=nums(i)
MVC PG,=CL80'.... :' clear buffer
LA R9,PG @pg
XDECO R8,XDEC edit n
MVC 0(4,R9),XDEC+8 output n
LA R9,7(R9) @pg+=7
LA R7,1 j=1
DO WHILE=(C,R7,LE,=A(13)) do j=1 to 13
LR R1,R7 j
SLA R1,1 ~
LH R3,ARABIC-2(R1) aj=arabic(j)
DO WHILE=(CR,R8,GE,R3) while n>=aj
LR R1,R7 j
SLA R1,1 ~
LA R4,ROMAN-2(R1) roman(j)
MVC 0(2,R9),0(R4) output roman(j)
IF CLI,1(R9),NE,C' ' THEN if roman(j)[2]=' ' then
LA R9,2(R9) @pg+=2
ELSE , else
LA R9,1(R9) @pg+=1
ENDIF , endif
SR R8,R3 n-=aj
ENDDO , endwile
LA R7,1(R7) j++
ENDDO , enddo j
XPRNT PG,L'PG print buffer
LA R6,1(R6) i++
ENDDO , enddo i
L R13,4(0,R13) restore previous savearea pointer
RETURN (14,12),RC=0 restore registers from calling save
ARABIC DC H'1000',H'900',H'500',H'400',H'100',H'90'
DC H'50',H'40',H'10',H'9',H'5',H'4',H'1'
ROMAN DC CL2'M',CL2'CM',CL2'D',CL2'CD',CL2'C',CL2'XC'
DC CL2'L',CL2'XL',CL2'X',CL2'IX',CL2'V',CL2'IV',CL2'I'
NUMS DC H'14',H'16',H'21',H'888',H'1492',H'1999',H'2020',H'3999'
PG DS CL80 buffer
XDEC DS CL12 temp for xdeco
REGEQU
END ROMAENC</syntaxhighlight>
{{out}}
<pre>
14 : XIV
16 : XVI
21 : XXI
888 : DCCCLXXXVIII
1492 : MCDXCII
1999 : MCMXCIX
2020 : MMXX
3999 : MMMCMXCIX
</pre>
 
=={{header|8080 Assembly}}==
<syntaxhighlight lang="8080asm"> org 100h
jmp test
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Takes a 16-bit integer in HL, and stores it
;; as a 0-terminated string starting at BC.
;; On exit, all registers destroyed; BC pointing at
;; end of string.
mkroman: push h ; put input on stack
lxi h,mkromantab
mkromandgt: mov a,m ; scan ahead to next entry
ana a
inx h
jnz mkromandgt
xthl ; load number
mov a,h ; if zero, we're done
ora l
jz mkromandone
xthl ; load next entry from table
mov e,m ; de = number
inx h
mov d,m
inx h
xthl ; load number
xra a ; find how many we need
subtract: inr a ; with trial subtraction
dad d
jc subtract
push psw ; keep counter
mov a,d ; we subtracted one too many
cma ; so we need to add one back
mov d,a
mov a,e
cma
mov e,a
inx d
dad d
pop d ; restore counter (into D)
xthl ; load table pointer
stringouter: dcr d ; do we need to include one?
jz mkromandgt
push h ; keep string location
stringinner: mov a,m ; copy string into target
stax b
ana a ; done yet?
jz stringdone
inx h
inx b ; copy next character
jmp stringinner
stringdone: pop h ; restore string location
jmp stringouter
mkromandone: pop d ; remove temporary variable from stack
ret
mkromantab: db 0
db 18h,0fch,'M',0 ; The value for each entry
db 7ch,0fch,'CM',0 ; is stored already negated
db 0ch,0feh,'D',0 ; so that it can be immediately
db 70h,0feh,'CD',0 ; added using `dad'.
db 9ch,0ffh,'C',0 ; This also has the convenient
db 0a6h,0ffh,'XC',0 ; property of not having any
db 0ceh,0ffh,'L',0 ; zero bytes except the string
db 0d8h,0ffh,'XL',0 ; and row terminators.
db 0f6h,0ffh,'X',0
db 0f7h,0ffh,'IX',0
db 0fbh,0ffh,'V',0
db 0fch,0ffh,'IV',0
db 0ffh,0ffh,'I',0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test code
test: mvi c,10 ; read string from console
lxi d,dgtbufdef
call 5
lxi h,0 ; convert to integer
lxi b,dgtbuf
readdgt: ldax b
ana a
jz convert
dad h ; hl *= 10
mov d,h
mov e,l
dad h
dad h
dad d
sui '0'
mov e,a
mvi d,0
dad d
inx b
jmp readdgt
convert: lxi b,romanbuf ; convert to roman
call mkroman
mvi a,'$' ; switch string terminator
stax b
mvi c,9 ; output result
lxi d,romanbuf
jmp 5
nl: db 13,10,'$'
dgtbufdef: db 5,0
dgtbuf: ds 6
romanbuf:</syntaxhighlight>
 
=={{header|8086 Assembly}}==
===Main and Supporting Functions===
The main program and test values: 70,1776,2021,3999,4000
<syntaxhighlight lang="asm"> mov ax,0070h
call EncodeRoman
mov si,offset StringRam
call PrintString
call NewLine
mov ax,1776h
call EncodeRoman
mov si,offset StringRam
call PrintString
call NewLine
 
mov ax,2021h
call EncodeRoman
mov si,offset StringRam
call PrintString
call NewLine
 
mov ax,3999h
call EncodeRoman
mov si,offset StringRam
call PrintString
call NewLine
mov ax,4000h
call EncodeRoman
mov si,offset StringRam
 
ReturnToDos ;macro that calls the int that exits dos</syntaxhighlight>
 
The <code>EncodeRoman</code> routine:
<syntaxhighlight lang="asm">;ROMAN NUMERALS MODULE
 
EncodeRoman:
;takes a BCD value in AX and stores its Roman numeral equivalent in ram.
 
call UnpackBCD
cmp dh,03h
jng continue_EncodeRoman
;roman numerals only go up to 3999.
jmp errorhandler_encodeRoman_inputTooBig
continue_EncodeRoman:
mov si,offset StringRam
;using SI as destination of roman numerals.
push ax
push cx
mov ch,0
mov cl,dh ;loop counter
cmp dh,0
jz skipThousands
encodeRoman_handleThousands:
mov al,"M"
mov [ds:si],al ;store in string ram
inc si
; call PrintChar
loop encodeRoman_handleThousands
skipThousands:
pop cx
pop ax
encodeRoman_HandleHundreds:
pushall
mov bh,0
mov bl,dl ;use bx as an offset into Roman_Lookup_Master
SHL bl,1
SHL bl,1 ;multiply by 2, we are indexing into a table with 4 bytes per row.
mov di,offset Roman_Lookup_Master
mov cx,4
getChar_Hundreds:
mov al,[bx+es:di] ;get first char index
push bx
push di
mov di,offset Roman_Hund
mov bl,al
mov al,[bx+es:di]
cmp al,0
jz skipNullChar_RomanHund
mov [ds:si],al ;store in ram
inc si
; call PrintChar
skipNullChar_RomanHund:
pop di
pop bx
inc di
loop getChar_Hundreds
popall
encodeRoman_HandleTens:
pushall
mov bh,0
mov bl,ah ;use bx as an offset into Roman_Lookup_Master
SHL bl,1
SHL bl,1 ;multiply by 2, we are indexing into a table with 4 bytes per row.
mov di,offset Roman_Lookup_Master
mov cx,4
getChar_Tens:
mov al,[bx+es:di] ;get first char index
push bx
push di
mov di,offset Roman_Tens
mov bl,al
mov al,[bx+es:di]
cmp al,0
jz skipNullChar_RomanTens
mov [ds:si],al ;store in ram
inc si
; call PrintChar
skipNullChar_RomanTens:
pop di
pop bx
inc di
loop getChar_Tens
popall
encodeRoman_HandleOnes:
pushall
mov bh,0
mov bl,al ;use bx as an offset into Roman_Lookup_Master
SHL bl,1
SHL bl,1 ;multiply by 2, we are indexing into a table with 4 bytes per row.
mov di,offset Roman_Lookup_Master
mov cx,4
getChar_Ones:
mov al,[bx+es:di] ;get first char index
push bx
push di
mov di,offset Roman_Ones
mov bl,al
mov al,[bx+es:di]
cmp al,0
jz skipNullChar_RomanOnes
mov [ds:si],al ;store in ram
inc si
; call PrintChar
skipNullChar_RomanOnes:
pop di
pop bx
inc di
loop getChar_Ones
popall
mov al,0
mov [ds:si],al ;place a null terminator at the end of the string.
ret
 
errorhandler_encodeRoman_inputTooBig:
push ds
push ax
LoadSegment ds,ax,@data
mov al,01h
mov byte ptr [ds:error_code],al
mov ax, offset EncodeRoman
mov word ptr [ds:error_routine],ax
LoadSegment ds,ax,@code
mov si,offset Roman_Error
call PrintString
pop ax
pop ds
stc ;set carry, allowing program to branch if error occurred.
ret
 
 
Roman_Lookup_Master db 0,0,0,0 ;0
db 0,0,0,1 ;1
db 0,0,1,1 ;2
db 0,1,1,1 ;3
db 0,0,1,2 ;4
db 0,0,0,2 ;5
db 0,0,2,1 ;6
db 0,2,1,1 ;7
db 2,1,1,1 ;8
db 0,0,1,3 ;9
 
Roman_Ones db 0,"IVX" ;the same pattern is used regardless of what power of 10 we're working with
Roman_Tens db 0,"XLC"
Roman_Hund db 0,"CDM"
 
Roman_Error db "ERROR: BAD INPUT",0
 
 
UnpackBCD:
;converts a "packed" BCD value in AX to an "unpacked" value in DX.AX
;DX is the high byte, AX is the low byte.
;CLOBBERS DX AND AX.
mov dx,0
mov dl,ah
mov ah,0
push cx
mov cl,4
rol dx,cl
;BEFORE: DX = 00XYh
;AFTER: DX = 0XY0h
ror dl,cl ;DX = 0X0Yh
rol ax,cl
;BEFORE: AX = 00XYh
;AFTER: AX = 0XY0h
ror al,cl ;AX = 0X0Yh
pop cx
ret</syntaxhighlight>
 
Macros used:
<syntaxhighlight lang="asm">pushall macro
push ax
push bx
push cx
push dx
push ds
push es
push di
;I forgot SI in this macro, but once you add it in the code stops working! So I left it out.
endm
 
popall macro
pop di
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
endm</syntaxhighlight>
===Output===
{{out}}
<pre>
LXX
MDCCLXXVI
MMXXI
MMMCMXCIX
ERROR: BAD INPUT
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE PTR="CARD"
CARD ARRAY arabic=[1000 900 500 400 100 90 50 40 10 9 5 4 1]
PTR ARRAY roman(13)
 
PROC InitRoman()
roman(0)="M" roman(1)="CM" roman(2)="D" roman(3)="CD"
roman(4)="C" roman(5)="XC" roman(6)="L" roman(7)="XL"
roman(8)="X" roman(9)="IX" roman(10)="V" roman(11)="IV" roman(12)="I"
RETURN
 
PROC EncodeRomanNumber(CARD n CHAR ARRAY res)
BYTE i,len
CHAR ARRAY tmp
 
res(0)=0 len=0
FOR i=0 TO 12
DO
WHILE arabic(i)<=n
DO
tmp=roman(i)
SAssign(res,tmp,len+1,len+1+tmp(0))
len==+tmp(0)
n==-arabic(i)
OD
OD
res(0)=len
RETURN
 
PROC Main()
CARD ARRAY data=[1990 2008 5555 1666 3888 3999]
BYTE i
CHAR ARRAY r(20)
 
InitRoman()
FOR i=0 TO 5
DO
EncodeRomanNumber(data(i),r)
PrintF("%U=%S%E",data(i),r)
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Roman_numerals_encode.png Screenshot from Atari 8-bit computer]
<pre>
1990=MCMXC
2008=MMVIII
5555=MMMMMDLV
1666=MDCLXVI
3888=MMMDCCCLXXXVIII
3999=MMMCMXCIX
</pre>
 
=={{header|ActionScript}}==
<langsyntaxhighlight ActionScriptlang="actionscript">function arabic2roman(num:Number):String {
var lookup:Object = {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 roman:String = "", i:String;
Line 19 ⟶ 506:
trace("2008 in roman is " + arabic2roman(2008));
trace("1666 in roman is " + arabic2roman(1666));
</syntaxhighlight>
</lang>
{{out}}
Output:
<pre>1990 in roman is MCMXC
2008 in roman is MMVIII
Line 26 ⟶ 513:
</pre>
And the reverse:
<langsyntaxhighlight ActionScriptlang="actionscript">function roman2arabic(roman:String):Number {
var romanArr:Array = roman.toUpperCase().split('');
var lookup:Object = {I:1, V:5, X:10, L:50, C:100, D:500, M:1000};
Line 38 ⟶ 525:
trace("MCMXC in arabic is " + roman2arabic("MCMXC"));
trace("MMVIII in arabic is " + roman2arabic("MMVIII"));
trace("MDCLXVI in arabic is " + roman2arabic("MDCLXVI"));</langsyntaxhighlight>
{{out}}
Output:
<pre>MCMXC in arabic is 1990
MMVIII in arabic is 2008
Line 45 ⟶ 532:
 
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
 
procedure Roman_Numeral_Test is
Line 77 ⟶ 564:
Put_Line (To_Roman (25));
Put_Line (To_Roman (944));
end Roman_Numeral_Test;</langsyntaxhighlight>
{{out}}
Output:
<pre>
MCMXCIX
XXV
CMXLIV
</pre>
 
=={{header|ALGOL 68}}==
Line 89 ⟶ 578:
 
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d]}}
<langsyntaxhighlight lang="algol68">[]CHAR roman = "MDCLXVmdclxvi"; # UPPERCASE for thousands #
[]CHAR adjust roman = "CCXXmmccxxii";
[]INT arabic = (1000000, 500000, 100000, 50000, 10000, 5000, 1000, 500, 100, 50, 10, 5, 1);
Line 117 ⟶ 606:
print((val, " - ", arabic to roman(val), new line))
OD
)</langsyntaxhighlight>
Output{{out}} (last example is manually wrapped):
<pre style="height:30ex;overflow:scroll">
+1 - i
Line 213 ⟶ 702:
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMCDLXXXmmmdcxlvii</pre>
 
=={{header|ALGOL W}}==
<!-- {{works with|ALGOL W|Standard - no extensions to language used}} -->
{{works with|awtoc|any - tested with release [http://www.jampan.co.nz/~glyn/aw2c.tar.gz Mon Apr 27 14:25:27 NZST 2009]}}
<!-- This specimen was emailed to be by Glyn Webster > "Here's a Roman number procedure that would fit in:" -->
<langsyntaxhighlight lang="algolw">BEGIN
 
PROCEDURE ROMAN (INTEGER VALUE NUMBER; STRING(15) RESULT CHARACTERS; INTEGER RESULT LENGTH);
Line 267 ⟶ 757:
ROMAN(2009, S, I); WRITE(S, I);
ROMAN(405, S, I); WRITE(S, I);
END.</langsyntaxhighlight>
{{out}}
Output:
<pre>
I 1
Line 276 ⟶ 766:
CDV 3
</pre>
 
=={{header|APL}}==
{{works with|Dyalog APL}}
<syntaxhighlight lang="apl">toRoman←{
⍝ Digits and corresponding values
ds←((⊢≠⊃)⊆⊢)' M CM D CD C XC L XL X IX V IV I'
vs←1000, ,100 10 1∘.×9 5 4 1
⍝ Input ≤ 0 is invalid
⍵≤0:⎕SIGNAL 11
{ 0=d←⊃⍸vs≤⍵:⍬ ⍝ Find highest digit in number
(d⊃ds),∇⍵-d⊃vs ⍝ While one exists, add it and subtract from number
}⍵
}</syntaxhighlight>
 
{{out}}
 
<pre> toRoman¨ 1990 2008 1666 2021
MCMXC MMVIII MDCLXVI MMXXI </pre>
 
=={{header|AppleScript}}==
{{Trans|JavaScript}}
(ES6 version)
{{Trans|Haskell}}
(mapAccumL version)
<syntaxhighlight lang="applescript">------------------ ROMAN INTEGER STRINGS -----------------
 
-- roman :: Int -> String
on roman(n)
set kvs to {["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]}
script stringAddedValueDeducted
on |λ|(balance, kv)
set {k, v} to kv
set {q, r} to quotRem(balance, v)
if q > 0 then
{r, concat(replicate(q, k))}
else
{r, ""}
end if
end |λ|
end script
concat(snd(mapAccumL(stringAddedValueDeducted, n, kvs)))
end roman
 
 
--------------------------- TEST -------------------------
on run
map(roman, [2016, 1990, 2008, 2000, 1666])
--> {"MMXVI", "MCMXC", "MMVIII", "MM", "MDCLXVI"}
end run
 
 
---------------- GENERIC LIBRARY FUNCTIONS ---------------
 
-- concat :: [[a]] -> [a] | [String] -> String
on concat(xs)
script append
on |λ|(a, b)
a & b
end |λ|
end script
if length of xs > 0 and ¬
class of (item 1 of xs) is string then
set unit to ""
else
set unit to {}
end if
foldl(append, unit, xs)
end concat
 
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
 
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
 
-- 'The mapAccumL function behaves like a combination of map and foldl;
-- it applies a function to each element of a list, passing an
-- accumulating parameter from left to right, and returning a final
-- value of this accumulator together with the new list.' (see Hoogle)
 
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
on mapAccumL(f, acc, xs)
script
on |λ|(a, x)
tell mReturn(f) to set pair to |λ|(item 1 of a, x)
[item 1 of pair, (item 2 of a) & {item 2 of pair}]
end |λ|
end script
foldl(result, [acc, {}], xs)
end mapAccumL
 
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
 
-- quotRem :: Integral a => a -> a -> (a, a)
on quotRem(m, n)
{m div n, m mod n}
end quotRem
 
-- Egyptian multiplication - progressively doubling a list, appending
-- stages of doubling to an accumulator where needed for binary
-- assembly of a target length
 
-- replicate :: Int -> a -> [a]
on replicate(n, a)
set out to {}
if n < 1 then return out
set dbl to {a}
repeat while (n > 1)
if (n mod 2) > 0 then set out to out & dbl
set n to (n div 2)
set dbl to (dbl & dbl)
end repeat
return out & dbl
end replicate
 
-- snd :: (a, b) -> b
on snd(xs)
if class of xs is list and length of xs = 2 then
item 2 of xs
else
missing value
end if
end snd</syntaxhighlight>
{{Out}}
<pre>{"MMXVI", "MCMXC", "MMVIII", "MM", "MDCLXVI"}</pre>
 
=={{header|Arturo}}==
{{trans|Nim}}
<syntaxhighlight lang="rebol">nums: [[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"])
toRoman: function [x][
ret: ""
idx: 0
initial: x
loop nums 'num [
d: num\0
l: num\1
 
i: 0
while [i<initial/d] [
ret: ret ++ l
i: i+1
]
 
initial: mod initial d
]
return ret
]
loop [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 25 30 40
50 60 69 70 80 90 99 100 200 300 400 500 600 666 700 800 900
1000 1009 1444 1666 1945 1997 1999 2000 2008 2010 2011 2500
3000 3999] 'n
-> print [n "->" toRoman n]</syntaxhighlight>
 
{{out}}
 
<pre>1 -> I
2 -> II
3 -> III
4 -> IV
5 -> V
6 -> VI
7 -> VII
8 -> VIII
9 -> IX
10 -> X
11 -> XI
12 -> XII
13 -> XIII
14 -> XIV
15 -> XV
16 -> XVI
17 -> XVII
18 -> XVIII
19 -> XIX
20 -> XX
25 -> XXV
30 -> XXX
40 -> XL
50 -> L
60 -> LX
69 -> LXIX
70 -> LXX
80 -> LXXX
90 -> XC
99 -> XCIX
100 -> C
200 -> CC
300 -> CCC
400 -> CD
500 -> D
600 -> DC
666 -> DCLXVI
700 -> DCC
800 -> DCCC
900 -> CM
1000 -> M
1009 -> MIX
1444 -> MCDXLIV
1666 -> MDCLXVI
1945 -> MCMXLV
1997 -> MCMXCVII
1999 -> MCMXCIX
2000 -> MM
2008 -> MMVIII
2010 -> MMX
2011 -> MMXI
2500 -> MMD
3000 -> MMM
3999 -> MMMCMXCIX</pre>
 
=={{header|AutoHotkey}}==
{{trans|C++}}
<langsyntaxhighlight AutoHotkeylang="autohotkey">MsgBox % stor(444)
 
stor(value)
Line 306 ⟶ 1,046:
}
Return result . "O"
}</langsyntaxhighlight>
 
=={{header|Autolisp}}==
<syntaxhighlight lang="autolisp">
(defun c:roman() (romanNumber (getint "\n Enter number > "))
(defun romanNumber (n / uni dec hun tho nstr strlist nlist rom)
(if (and (> n 0) (<= n 3999))
(progn
(setq
UNI (list "" "I" "II" "III" "IV" "V" "VI" "VII" "VIII" "IX")
DEC (list "" "X" "XX" "XXX" "XL" "L" "LX" "LXX" "LXXX" "XC")
HUN (list "" "C" "CC" "CCC" "CD" "D" "DC" "DCC" "DCCC" "CM")
THO (list "" "M" "MM" "MMM")
nstr (itoa n)
)
(while (> (strlen nstr) 0) (setq strlist (append strlist (list (substr nstr 1 1))) nstr (substr nstr 2 (strlen nstr))))
(setq nlist (mapcar 'atoi strlist))
(cond
((> n 999)(setq rom(strcat(nth (car nlist) THO)(nth (cadr nlist) HUN)(nth (caddr nlist) DEC) (nth (last nlist)UNI ))))
((and (> n 99)(<= n 999))(setq rom(strcat (nth (car nlist) HUN)(nth (cadr nlist) DEC) (nth (last nlist)UNI ))))
((and (> n 9)(<= n 99))(setq rom(strcat (nth (car nlist) DEC) (nth (last nlist)UNI ))))
((<= n 9)(setq rom(nth (last nlist)UNI)))
)
)
(princ "\nNumber out of range!")
)
rom
)
</syntaxhighlight>
{{out}}
<pre>
1577 "MDLXXVII"
3999 "MMMCMXCIX"
888 "DCCCLXXXVIII"
159 "CLIX"
</pre>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f ROMAN_NUMERALS_ENCODE.AWK
BEGIN {
Line 336 ⟶ 1,111:
return(roman1000[v] roman100[w] roman10[x] roman1[y])
}
</syntaxhighlight>
</lang>
{{out}}
<p>output:
</p>
<pre>
1990 = MCMXC
Line 346 ⟶ 1,120:
 
=={{header|BASIC}}==
==={{header|Applesoft BASIC}}===
{{works with|FreeBASIC}}
<syntaxhighlight lang="gwbasic"> 1 N = 1990: GOSUB 5: PRINT N" = "V$
<lang freebasic>
2 N = 2008: GOSUB 5: PRINT N" = "V$
DIM SHARED arabic(0 TO 12) AS Integer => {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }
3 N = 1666: GOSUB 5: PRINT N" = "V$;
DIM SHARED roman(0 TO 12) AS String*2 => {"M", "CM", "D","CD", "C","XC","L","XL","X","IX","V","IV","I"}
4 END
5 V = N:V$ = "": FOR I = 0 TO 12: FOR L = 1 TO 0 STEP 0:A = VAL ( MID$ ("1E3900500400100+90+50+40+10+09+05+04+01",I * 3 + 1,3))
6 L = (V - A) > = 0:V$ = V$ + MID$ ("M.CMD.CDC.XCL.XLX.IXV.IVI",I * 2 + 1,(I - INT (I / 2) * 2 + 1) * L):V = V - A * L: NEXT L,I
7 RETURN</syntaxhighlight>
 
==={{header|ASIC}}===
FUNCTION toRoman(value AS Integer) AS String
{{trans|DWScript}}
DIM i AS Integer
<syntaxhighlight lang="basic">
DIM result AS String
REM Roman numerals/Encode
DIM Weights(12)
FOR i = 0 TO 12
DIM Symbols$(12)
DO WHILE value >= arabic(i)
DATA 1000, "M", 900, "CM", 500, "D", 400, "CD", 100, "C", 90, "XC", 50, "L"
result = result + roman(i)
DATA 40, "XL", 10, "X", 9, "IX", 5, "V", 4, "IV", 1, "I"
value = value - arabic(i)
REM 3888 or MMMDCCCLXXXVIII (15 chars) is the longest string properly encoded
LOOP
REM with these symbols.
NEXT i
FOR J = 0 TO 12
toRoman = result
READ Weights(J)
END FUNCTION
READ Symbols$(J)
NEXT J
 
AValue = 1990
'Testing
GOSUB ToRoman:
PRINT "2009 = "; toRoman(2009)
PRINT "1666Roman$ = "; toRoman(1666)
REM MCMXC
PRINT "3888 = "; toRoman(3888)
AValue = 2022
</lang>
GOSUB ToRoman:
PRINT Roman$
REM MMXXII
AValue = 3888
GOSUB ToRoman:
PRINT Roman$
REM MMMDCCCLXXXVIII
END
 
ToRoman:
Output
REM Result: Roman$
2009 = MMIX
Roman$ = ""
1666 = MDCLXVI
I = 0
3888 = MMMDCCCLXXXVIII
Loop:
IF (I > 12 THEN ExitToRoman:
IF AValue <= 0 THEN ExitToRoman:
WHILE AValue >= Weights(I)
Roman$ = Roman$ + Symbols$(I)
AValue = AValue - Weights(I)
WEND
I = I + 1
GOTO Loop:
ExitToRoman:
RETURN
</syntaxhighlight>
 
=== {{header|ZX Spectrum BasicBaCon}} ===
<syntaxhighlight lang="bacon">OPTION BASE 1
<lang zxbasic> 10 DATA 1000,"M",900,"CM"
 
20 DATA 500,"D",400,"CD"
GLOBAL roman$[] = { "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" }
30 DATA 100,"C",90,"XC"
GLOBAL number[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }
40 DATA 50,"L",40,"XL"
 
50 DATA 10,"X",9,"IX"
FUNCTION toroman$(value)
60 DATA 5,"V",4,"IV",1,"I"
 
70 INPUT "Enter an arabic number: ";V
LOCAL result$
80 LET VALUE=V
90 LET V$=""
100 FOR I=0 TO 12
110 READ A,R$
120 IF V<A THEN GO TO 160
130 LET V$=V$+R$
140 LET V=V-A
150 GO TO 120
160 NEXT I
170 PRINT VALUE;"=";V$</lang>
 
DOTIMES UBOUND(number)
=={{header|BASIC256}}==
WHILE value >= number[_]
result$ = result$ & roman$[_]
DECR value, number[_]
WEND
DONE
 
RETURN result$
 
ENDFUNC
 
PRINT toroman$(1990)
PRINT toroman$(2008)
PRINT toroman$(1666)
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMVIII
MDCLXVI
</pre>
 
==={{header|BASIC256}}===
{{works with|BASIC256 }}
<langsyntaxhighlight lang="basic256">
print 1666+" = "+convert$(1666)
print 2008+" = "+convert$(2008)
Line 413 ⟶ 1,226:
next i
end function
</syntaxhighlight>
</lang>
{{out}}
Output:
<pre>
1666 = MDCLXVI
Line 422 ⟶ 1,235:
</pre>
 
==={{header|BBC BASIC}}===
<langsyntaxhighlight lang="bbcbasic"> PRINT ;1999, FNroman(1999)
PRINT ;2012, FNroman(2012)
PRINT ;1666, FNroman(1666)
Line 440 ⟶ 1,253:
ENDWHILE
NEXT
= r$</langsyntaxhighlight>
{{out}}
Output:
<pre>
1999 MCMXCIX
Line 448 ⟶ 1,261:
3888 MMMDCCCLXXXVIII
</pre>
 
==={{header|Chipmunk Basic}}===
{{works with|Chipmunk Basic|3.6.4}}
{{trans|GW-BASIC}}
<syntaxhighlight lang="qbasic">100 cls
110 dim arabic(12), roman$(12)
120 for j = 0 to 12 : read arabic(j),roman$(j) : next j
130 data 1000,"M", 900,"CM", 500,"D", 400,"CD", 100,"C", 90,"XC"
140 data 50,"L",40,"XL",10,"X",9,"IX",5,"V",4,"IV",1,"I"
187 avalor = 1990 : print avalor "= "; : gosub 220 : print roman$ ' MCMXC
188 avalor = 2008 : print avalor "= "; : gosub 220 : print roman$ ' MMXXII
189 avalor = 1666 : print avalor "= "; : gosub 220 : print roman$ ' MDCLXVI
200 end
210 rem Encode to Roman
220 roman$ = "" : i = 0
230 while (i <= 12) and (avalor > 0)
240 while avalor >= arabic(i)
250 roman$ = roman$+roman$(i)
260 avalor = avalor-arabic(i)
270 wend
280 i = i+1
290 wend
300 return</syntaxhighlight>
{{out}}
<pre>1990 = MCMXC
2008 = MMVIII
1666 = MDCLXVI</pre>
 
==={{header|Commodore BASIC}}===
{{works with|Commodore BASIC|7.0}}
C-128 version:
<syntaxhighlight lang="basic">100 DIM RN$(12),NV(12)
110 FOR I=0 TO 12
120 : READ RN$(I), NV(I)
130 NEXT I
140 DATA M,1000, CM,900, D,500, CD,400
150 DATA C, 100, XC, 90, L, 50, XL, 40
160 DATA X, 10, IX, 9, V, 5, IV, 4
170 DATA I, 1
180 PRINT CHR$(19);CHR$(19);CHR$(147);CHR$(18);
190 PRINT "***** ROMAN NUMERAL ENCODER *****";CHR$(27);"T"
200 DO
210 : PRINT "ENTER NUMBER (0 TO QUIT):";
220 : OPEN 1,0:INPUT#1,AN$:CLOSE 1:PRINT
230 : AN=VAL(AN$):IF AN=0 THEN EXIT
240 : RN$=""
250 : DO WHILE AN > 0
260 : FOR I=0 TO 12
270 : IF AN >= NV(I) THEN BEGIN
280 : RN$ = RN$+ RN$(I)
290 : AN = AN - NV(I)
300 : GOTO 330
310 : BEND
320 : NEXT I
330 : LOOP
340 : PRINT RN$;CHR$(13)
350 LOOP</syntaxhighlight>
 
{{works with|Commodore BASIC|3.5}}
C-16/116/Plus-4 version (BASIC 3.5 has DO/LOOP but not BEGIN/BEND)
<syntaxhighlight lang="basic">100 DIM RN$(12),NV(12)
110 FOR I=0 TO 12
120 : READ RN$(I), NV(I)
130 NEXT I
140 DATA M,1000, CM,900, D,500, CD,400
150 DATA C, 100, XC, 90, L, 50, XL, 40
160 DATA X, 10, IX, 9, V, 5, IV, 4
170 DATA I, 1
180 PRINT CHR$(19);CHR$(19);CHR$(147);CHR$(18);
190 PRINT "***** ROMAN NUMERAL ENCODER *****";CHR$(27);"T"
200 DO
210 : PRINT "ENTER NUMBER (0 TO QUIT):";
220 : OPEN 1,0:INPUT#1,AN$:CLOSE 1:PRINT
230 : AN=VAL(AN$):IF AN=0 THEN EXIT
240 : RN$=""
250 : DO WHILE AN > 0
260 : FOR I=0 TO 12
270 : IF AN < NV(I) THEN 320
280 : RN$ = RN$+ RN$(I)
290 : AN = AN - NV(I)
300 : I = 12
320 : NEXT I
330 : LOOP
340 : PRINT RN$;CHR$(13)
350 LOOP</syntaxhighlight>
 
{{works with|Commodore BASIC|2.0}}
This version works on any Commodore, though the title banner should be adjusted to match the color and screen width of the particular machine.
<syntaxhighlight lang="basic">100 DIM RN$(12),NV(12)
110 FOR I=0 TO 12
120 : READ RN$(I), NV(I)
130 NEXT I
140 DATA M,1000, CM,900, D,500, CD,400
150 DATA C, 100, XC, 90, L, 50, XL, 40
160 DATA X, 10, IX, 9, V, 5, IV, 4
170 DATA I, 1
180 PRINT CHR$(19);CHR$(19);CHR$(147);CHR$(18);
190 PRINT "***** ROMAN NUMERAL ENCODER *****";
200 REM BEGIN MAIN LOOP
210 : PRINT "NUMBER (0 TO QUIT):";
220 : OPEN 1,0:INPUT#1,AN$:CLOSE 1:PRINT
230 : AN=VAL(AN$):IF AN=0 THEN END
240 : RN$=""
250 : IF AN <= 0 THEN 340
260 : FOR I=0 TO 12
270 : IF AN < NV(I) THEN 320
280 : RN$ = RN$+ RN$(I)
290 : AN = AN - NV(I)
300 : I = 12
320 : NEXT I
330 : GOTO 250
340 : PRINT RN$;CHR$(13)
350 GOTO 210
</syntaxhighlight>
 
The output is the same for all the above versions:
{{Out}}
<pre>***** ROMAN NUMERAL ENCODER *****
 
ENTER NUMBER (0 TO QUIT):2009
MMIX
 
ENTER NUMBER (0 TO QUIT):1666
MDCLXVI
 
ENTER NUMBER (0 TO QUIT):3888
MMMDCCCLXXXVIII
 
ENTER NUMBER (0 TO QUIT):0
 
READY.</pre>
 
==={{header|FreeBASIC}}===
{{works with|FreeBASIC}}
<syntaxhighlight lang="freebasic">
DIM SHARED arabic(0 TO 12) AS Integer => {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }
DIM SHARED roman(0 TO 12) AS String*2 => {"M", "CM", "D","CD", "C","XC","L","XL","X","IX","V","IV","I"}
 
FUNCTION toRoman(value AS Integer) AS String
DIM i AS Integer
DIM result AS String
FOR i = 0 TO 12
DO WHILE value >= arabic(i)
result = result + roman(i)
value = value - arabic(i)
LOOP
NEXT i
toRoman = result
END FUNCTION
 
'Testing
PRINT "2009 = "; toRoman(2009)
PRINT "1666 = "; toRoman(1666)
PRINT "3888 = "; toRoman(3888)
</syntaxhighlight>
 
{{out}}
<pre>
2009 = MMIX
1666 = MDCLXVI
3888 = MMMDCCCLXXXVIII
</pre>
 
Another solution:
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64
 
Function romanEncode(n As Integer) As String
If n < 1 OrElse n > 3999 Then Return "" '' can only encode numbers in range 1 to 3999
Dim roman1(0 To 2) As String = {"MMM", "MM", "M"}
Dim roman2(0 To 8) As String = {"CM", "DCCC", "DCC", "DC", "D", "CD", "CCC", "CC", "C"}
Dim roman3(0 To 8) As String = {"XC", "LXXX", "LXX", "LX", "L", "XL", "XXX", "XX", "X"}
Dim roman4(0 To 8) As String = {"IX", "VIII", "VII", "VI", "V", "IV", "III", "II", "I"}
Dim As Integer thousands, hundreds, tens, units
thousands = n \ 1000
n Mod= 1000
hundreds = n \ 100
n Mod= 100
tens = n \ 10
units = n Mod 10
Dim roman As String = ""
If thousands > 0 Then roman += roman1(3 - thousands)
If hundreds > 0 Then roman += roman2(9 - hundreds)
If tens > 0 Then roman += roman3(9 - tens)
If units > 0 Then roman += roman4(9 - units)
Return roman
End Function
 
Dim a(2) As Integer = {1990, 2008, 1666}
For i As Integer = 0 To 2
Print a(i); " => "; romanEncode(a(i))
Next
 
Print
Print "Press any key to quit"
Sleep</syntaxhighlight>
 
{{out}}
<pre>
1990 => MCMXC
2008 => MMVIII
1666 => MDCLXVI
</pre>
 
==={{header|FutureBasic}}===
<syntaxhighlight lang="futurebasic">window 1
 
local fn DecimaltoRoman( decimal as short ) as Str15
short arabic(12)
Str15 roman(12)
long i
Str15 result : result = ""
arabic(0) = 1000 : arabic(1) = 900 : arabic(2) = 500 : arabic(3) = 400
arabic(4) = 100 : arabic(5) = 90 : arabic(6) = 50 : arabic(7) = 40
arabic(8) = 10 : arabic(9) = 9 : arabic(10) = 5 : arabic(11) = 4: arabic(12) = 1
roman(0) = "M" : roman(1) = "CM" : roman(2) = "D" : roman(3) = "CD"
roman(4) = "C" : roman(5) = "XC" : roman(6) = "L" : roman(7) = "XL"
roman(8) = "X" : roman(9) = "IX" : roman(10) = "V" : roman(11) = "IV" : roman(12) = "I"
for i = 0 to 12
while ( decimal >= arabic(i) )
result = result + roman(i)
decimal = decimal - arabic(i)
wend
next i
if result == "" then result = "Zepherium"
end fn = result
 
print "1990 = "; fn DecimaltoRoman( 1990 )
print "2008 = "; fn DecimaltoRoman( 2008 )
print "2016 = "; fn DecimaltoRoman( 2016 )
print "1666 = "; fn DecimaltoRoman( 1666 )
print "3888 = "; fn DecimaltoRoman( 3888 )
print "1914 = "; fn DecimaltoRoman( 1914 )
print "1000 = "; fn DecimaltoRoman( 1000 )
print " 513 = "; fn DecimaltoRoman( 513 )
print " 33 = "; fn DecimaltoRoman( 33 )
 
HandleEvents</syntaxhighlight>
 
Output:
<pre>
1990 = MCMXC
2008 = MMVIII
2016 = MMXVI
1666 = MDCLXVI
3888 = MMMDCCCLXXXVIII
1914 = MCMXIV
1000 = M
513 = DXIII
33 = XXXIII
</pre>
 
==={{header|Gambas}}===
{{trans|FreeBASIC}}
<syntaxhighlight lang="vbnet">Public Sub Main()
'Testing
Print "2009 = "; toRoman(2009)
Print "1666 = "; toRoman(1666)
Print "3888 = "; toRoman(3888)
 
End
 
Function toRoman(value As Integer) As String
 
Dim result As String
Dim arabic As Integer[] = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
Dim roman As String[] = ["M", "CM", "D", "CD", "C", "XC", "L" , "XL", "X", "IX", "V", "IV", "I"]
 
For i As Integer = 0 To arabic.Max
Do While value >= arabic[i]
result &= roman[i]
value -= arabic[i]
Loop
Next
Return result
 
End Function</syntaxhighlight>
{{out}}
<pre>Same as FreeBASIC entry.</pre>
 
=== {{header|GW-BASIC}} ===
{{trans|DWScript}}
{{works with|BASICA}}
<syntaxhighlight lang="gwbasic">
10 REM Roman numerals/Encode
20 DIM WEIGHTS%(12), SYMBOLS$(12)
30 FOR J% = 0 TO 12: READ WEIGHTS%(J%), SYMBOLS$(J%): NEXT J%
40 DATA 1000, "M", 900, "CM", 500, "D", 400, "CD", 100, "C", 90, "XC"
50 DATA 50, "L", 40, "XL", 10, "X", 9, "IX", 5, "V", 4, "IV", 1, "I"
60 REM 3888 or MMMDCCCLXXXVIII (15 chars) is
70 REM the longest string properly encoded
80 REM with these symbols.
90 AVALUE% = 1990: GOSUB 1000: PRINT ROMAN$ ' MCMXC
100 AVALUE% = 2022: GOSUB 1000: PRINT ROMAN$ ' MMXXII
110 AVALUE% = 3888: GOSUB 1000: PRINT ROMAN$ ' MMMDCCCLXXXVIII
120 END
990 REM Encode to roman
1000 ROMAN$ = "": I% = 0
1010 WHILE (I% <= 12) AND (AVALUE% > 0)
1020 WHILE AVALUE% >= WEIGHTS%(I%)
1030 ROMAN$ = ROMAN$ + SYMBOLS$(I%)
1040 AVALUE% = AVALUE% - WEIGHTS%(I%)
1050 WEND
1060 I% = I% + 1
1070 WEND
1080 RETURN
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMXXII
MMMDCCCLXXXVIII
</pre>
 
==={{header|IS-BASIC}}===
<syntaxhighlight lang="is-basic">100 PROGRAM "Roman.bas"
110 DO
120 PRINT :INPUT PROMPT "Enter an arabic number: ":N
130 IF N<1 THEN EXIT DO
140 PRINT TOROMAN$(N)
150 LOOP
160 DEF TOROMAN$(X)
170 IF X>3999 THEN
180 LET TOROMAN$="Too big."
190 EXIT DEF
200 END IF
210 RESTORE
220 LET SUM$=""
230 FOR I=1 TO 13
240 READ ARABIC,ROMAN$
250 DO WHILE X>=ARABIC
260 LET SUM$=SUM$&ROMAN$
270 LET X=X-ARABIC
280 LOOP
290 NEXT
300 LET TOROMAN$=SUM$
310 END DEF
320 DATA 1000,"M",900,"CM",500,"D",400,"CD",100,"C",90,"XC"
330 DATA 50,"L",40,"XL",10,"X",9,"IX",5,"V",4,"IV",1,"I"</syntaxhighlight>
 
==={{header|Liberty BASIC}}===
{{works with|Just BASIC}}
<syntaxhighlight lang="lb">
dim arabic( 12)
for i =0 to 12
read k
arabic( i) =k
next i
data 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
 
dim roman$( 12)
for i =0 to 12
read k$
roman$( i) =k$
next i
data "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
 
print 2009, toRoman$( 2009)
print 1666, toRoman$( 1666)
print 3888, toRoman$( 3888)
 
end
 
function toRoman$( value)
i =0
result$ =""
for i = 0 to 12
while value >=arabic( i)
result$ = result$ + roman$( i)
value = value - arabic( i)
wend
next i
toRoman$ =result$
end function
</syntaxhighlight>
<pre>
2009 MMIX
1666 MDCLXVI
3888 MMMDCCCLXXXVIII
</pre>
 
==={{header|Microsoft Small Basic}}===
{{trans|DWScript}}
<syntaxhighlight lang="microsoftsmallbasic">
arabicNumeral = 1990
ConvertToRoman()
TextWindow.WriteLine(romanNumeral) 'MCMXC
arabicNumeral = 2018
ConvertToRoman()
TextWindow.WriteLine(romanNumeral) 'MMXVIII
arabicNumeral = 3888
ConvertToRoman()
TextWindow.WriteLine(romanNumeral) 'MMMDCCCLXXXVIII
Sub ConvertToRoman
weights[0] = 1000
weights[1] = 900
weights[2] = 500
weights[3] = 400
weights[4] = 100
weights[5] = 90
weights[6] = 50
weights[7] = 40
weights[8] = 10
weights[9] = 9
weights[10] = 5
weights[11] = 4
weights[12] = 1
symbols[0] = "M"
symbols[1] = "CM"
symbols[2] = "D"
symbols[3] = "CD"
symbols[4] = "C"
symbols[5] = "XC"
symbols[6] = "L"
symbols[7] = "XL"
symbols[8] = "X"
symbols[9] = "IX"
symbols[10] = "V"
symbols[11] = "IV"
symbols[12] = "I"
romanNumeral = ""
i = 0
While (i <= 12) And (arabicNumeral > 0)
While arabicNumeral >= weights[i]
romanNumeral = Text.Append(romanNumeral, symbols[i])
arabicNumeral = arabicNumeral - weights[i]
EndWhile
i = i + 1
EndWhile
EndSub
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMXVIII
MMMDCCCLXXXVIII
</pre>
 
==={{header|Nascom BASIC}}===
{{trans|DWScript}}
{{works with|Nascom ROM BASIC|4.7}}
<syntaxhighlight lang="basic">
10 REM Roman numerals/Encode
20 DIM WEIGHTS(12),SYMBOLS$(12)
30 FOR I=0 TO 12
40 READ WEIGHTS(I),SYMBOLS$(I)
50 NEXT I
60 DATA 1000,M,900,CM,500,D,400,CD,100,C,90,XC
70 DATA 50,L,40,XL,10,X,9,IX,5,V,4,IV,1,I
80 REM ** 3888 or MMMDCCCLXXXVIII (15 chars) is
90 REM the longest string properly encoded
100 REM with these symbols.
110 V=1990:GOSUB 500
120 PRINT ROMAN$:REM MCMXC
130 V=2022:GOSUB 500
140 PRINT ROMAN$:REM MMXXII
150 V=3888:GOSUB 500
160 PRINT ROMAN$:REM MMMDCCCLXXXVIII
170 END
490 REM ** Encode to roman
500 ROMAN$=""
510 I=0
520 IF I>12 OR V<=0 THEN RETURN
530 IF V<WEIGHTS(I) THEN 570
540 ROMAN$=ROMAN$+SYMBOLS$(I)
550 V=V-WEIGHTS(I)
560 GOTO 530
570 I=I+1
580 GOTO 520
590 RETURN
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMXXII
MMMDCCCLXXXVIII
</pre>
 
==={{header|PowerBASIC}}===
{{trans|BASIC}}
{{works with|PB/Win|8+}}
{{works with|PB/CC|5}}
<syntaxhighlight lang="powerbasic">FUNCTION toRoman(value AS INTEGER) AS STRING
DIM arabic(0 TO 12) AS INTEGER
DIM roman(0 TO 12) AS STRING
ARRAY ASSIGN arabic() = 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
ARRAY ASSIGN roman() = "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
 
DIM i AS INTEGER
DIM result AS STRING
 
FOR i = 0 TO 12
DO WHILE value >= arabic(i)
result = result & roman(i)
value = value - arabic(i)
LOOP
NEXT i
toRoman = result
END FUNCTION
 
FUNCTION PBMAIN
'Testing
? "2009 = " & toRoman(2009)
? "1666 = " & toRoman(1666)
? "3888 = " & toRoman(3888)
END FUNCTION</syntaxhighlight>
 
==={{header|PureBasic}}===
<syntaxhighlight lang="purebasic">#SymbolCount = 12 ;0 based count
DataSection
denominations:
Data.s "M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I" ;0-12
denomValues:
Data.i 1000,900,500,400,100,90,50,40,10,9,5,4,1 ;values in decending sequential order
EndDataSection
 
;-setup
Structure romanNumeral
symbol.s
value.i
EndStructure
Global Dim refRomanNum.romanNumeral(#SymbolCount)
 
Restore denominations
For i = 0 To #SymbolCount
Read.s refRomanNum(i)\symbol
Next
 
Restore denomValues
For i = 0 To #SymbolCount
Read refRomanNum(i)\value
Next
 
Procedure.s decRoman(n)
;converts a decimal number to a roman numeral
Protected roman$, i
For i = 0 To #SymbolCount
Repeat
If n >= refRomanNum(i)\value
roman$ + refRomanNum(i)\symbol
n - refRomanNum(i)\value
Else
Break
EndIf
ForEver
Next
 
ProcedureReturn roman$
EndProcedure
 
If OpenConsole()
 
PrintN(decRoman(1999)) ;MCMXCIX
PrintN(decRoman(1666)) ;MDCLXVI
PrintN(decRoman(25)) ;XXV
PrintN(decRoman(954)) ;CMLIV
 
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf</syntaxhighlight>
 
==={{header|QBasic}}===
<syntaxhighlight lang="qbasic">DIM SHARED arabic(0 TO 12)
DIM SHARED roman$(0 TO 12)
 
FUNCTION toRoman$ (value)
LET result$ = ""
FOR i = 0 TO 12
DO WHILE value >= arabic(i)
LET result$ = result$ + roman$(i)
LET value = value - arabic(i)
LOOP
NEXT i
toRoman$ = result$
END FUNCTION
 
FOR i = 0 TO 12
READ arabic(i), roman$(i)
NEXT i
 
DATA 1000, "M", 900, "CM", 500, "D", 400, "CD", 100, "C", 90, "XC"
DATA 50, "L", 40, "XL", 10, "X", 9, "IX", 5, "V", 4, "IV", 1, "I"
 
'Testing
PRINT "2009 = "; toRoman$(2009)
PRINT "1666 = "; toRoman$(1666)
PRINT "3888 = "; toRoman$(3888)</syntaxhighlight>
 
==={{header|Run BASIC}}===
<syntaxhighlight lang="runbasic">[loop]
input "Input value:";val$
print roman$(val$)
goto [loop]
 
' ------------------------------
' Roman numerals
' ------------------------------
FUNCTION roman$(val$)
a2r$ = "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"
v = val(val$)
for i = 1 to 13
r$ = word$(a2r$,i,",")
a = val(word$(r$,2,":"))
while v >= a
roman$ = roman$ + word$(r$,1,":")
v = v - a
wend
next i
END FUNCTION</syntaxhighlight>
 
==={{header|TI-83 BASIC}}===
<syntaxhighlight lang="ti83b">PROGRAM:DEC2ROM
:"="→Str1
:Lbl ST
:ClrHome
:Disp "NUMBER TO"
:Disp "CONVERT:"
:Input A
:If fPart(A) or A≠abs(A)
:Then
:Goto PI
:End
:A→B
:While B≥1000
:Str1+"M"→Str1
:B-1000→B
:End
:If B≥900
:Then
:Str1+"CM"→Str1
:B-900→B
:End
:If B≥500
:Then
:Str1+"D"→Str1
:B-500→B
:End
:If B≥400
:Then
:Str1+"CD"?Str1
:B-400→B
:End
:While B≥100
:Str1+"C"→Str1
:B-100→B
:End
:If B≥90
:Then
:Str1+"XC"→Str1
:B-90→B
:End
:If B≥50
:Then
:Str1+"L"→Str1
:B-50→B
:End
:If B≥40
:Then
:Str1+"XL"→Str1
:B-40→B
:End
:While B≥10
:Str1+"X"→Str1
:B-10→B
:End
:If B≥9
:Then
:Str1+"IX"→Str1
:B-9→B
:End
:If B≥5
:Then
:Str1+"V"→Str1
:B-5→B
:End
:If B≥4
:Then
:Str1+"IV"→Str1
:B-4→B
:End
:While B>0
:Str1+"I"→Str1
:B-1→B
:End
:ClrHome
:Disp A
:Disp Str1
:Stop
:Lbl PI
:ClrHome
:Disp "THE NUMBER MUST"
:Disp "BE A POSITIVE"
:Disp "INTEGER."
:Pause
:Goto ST
</syntaxhighlight>
 
==={{header|True BASIC}}===
<syntaxhighlight lang="qbasic">OPTION BASE 0
DIM arabic(12), roman$(12)
 
FOR i = 0 to 12
READ arabic(i), roman$(i)
NEXT i
 
DATA 1000, "M", 900, "CM", 500, "D", 400, "CD", 100, "C", 90, "XC"
DATA 50, "L", 40, "XL", 10, "X", 9, "IX", 5, "V", 4, "IV", 1, "I"
 
FUNCTION toRoman$(value)
LET result$ = ""
FOR i = 0 TO 12
DO WHILE value >= arabic(i)
LET result$ = result$ & roman$(i)
LET value = value - arabic(i)
LOOP
NEXT i
LET toRoman$ = result$
END FUNCTION
 
!Testing
PRINT "2009 = "; toRoman$(2009)
PRINT "1666 = "; toRoman$(1666)
PRINT "3888 = "; toRoman$(3888)
END</syntaxhighlight>
 
==={{header|uBasic/4tH}}===
{{trans|BBC Basic}}
<syntaxhighlight lang="text">Push 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000
' Initialize array
For i = 12 To 0 Step -1
@(i) = Pop()
Next
' Calculate and print numbers
Print 1999, : Proc _FNroman (1999)
Print 2014, : Proc _FNroman (2014)
Print 1666, : Proc _FNroman (1666)
Print 3888, : Proc _FNroman (3888)
 
End
 
_FNroman Param (1) ' ( n --)
Local (1) ' Define b@
' Try all numbers in array
For b@ = 12 To 0 Step -1
Do While a@ > @(b@) - 1 ' Several occurences of same number?
GoSub ((b@ + 1) * 10) ' Print roman digit
a@ = a@ - @(b@) ' Decrement number
Loop
Next
 
Print ' Terminate line
Return
' Print roman digits
10 Print "I"; : Return
20 Print "IV"; : Return
30 Print "V"; : Return
40 Print "IX"; : Return
50 Print "X"; : Return
60 Print "XL"; : Return
70 Print "L"; : Return
80 Print "XC"; : Return
90 Print "C"; : Return
100 Print "CD"; : Return
110 Print "D"; : Return
120 Print "CM"; : Return
130 Print "M"; : Return</syntaxhighlight>
 
==={{header|Visual Basic}}===
{{trans|BASIC}}
 
<syntaxhighlight lang="vb">Function toRoman(value) As String
Dim arabic As Variant
Dim roman As Variant
 
arabic = Array(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
roman = Array("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I")
 
Dim i As Integer, result As String
 
For i = 0 To 12
Do While value >= arabic(i)
result = result + roman(i)
value = value - arabic(i)
Loop
Next i
 
toRoman = result
End Function
 
Sub Main()
MsgBox toRoman(Val(InputBox("Number, please")))
End Sub</syntaxhighlight>
 
==={{header|XBasic}}===
{{trans|DWScript}}
{{works with|Windows XBasic}}
<syntaxhighlight lang="xbasic">
PROGRAM "romanenc"
VERSION "0.0000"
 
DECLARE FUNCTION Entry()
INTERNAL FUNCTION ToRoman$(aValue%%)
 
' 3888 or MMMDCCCLXXXVIII (15 chars) is the longest string properly encoded with these symbols.
 
FUNCTION Entry()
PRINT ToRoman$(1990) ' MCMXC
PRINT ToRoman$(2018) ' MMXVIII
PRINT ToRoman$(3888) ' MMMDCCCLXXXVIII
END FUNCTION
 
FUNCTION ToRoman$(aValue%%)
DIM weights%%[12]
DIM symbols$[12]
 
weights%%[0] = 1000
weights%%[1] = 900
weights%%[2] = 500
weights%%[3] = 400
weights%%[4] = 100
weights%%[5] = 90
weights%%[6] = 50
weights%%[7] = 40
weights%%[8] = 10
weights%%[9] = 9
weights%%[10] = 5
weights%%[11] = 4
weights%%[12] = 1
 
symbols$[0] = "M"
symbols$[1] = "CM"
symbols$[2] = "D"
symbols$[3] = "CD"
symbols$[4] = "C"
symbols$[5] = "XC"
symbols$[6] = "L"
symbols$[7] = "XL"
symbols$[8] = "X"
symbols$[9] = "IX"
symbols$[10] = "V"
symbols$[11] = "IV"
symbols$[12] = "I"
 
destination$ = ""
i@@ = 0
DO WHILE (i@@ <= 12) AND (aValue%% > 0)
DO WHILE aValue%% >= weights%%[i@@]
destination$ = destination$ + symbols$[i@@]
aValue%% = aValue%% - weights%%[i@@]
LOOP
i@@ = i@@ + 1
LOOP
RETURN destination$
END FUNCTION
END PROGRAM
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMXVIII
MMMDCCCLXXXVIII
</pre>
 
==={{header|Yabasic}}===
<syntaxhighlight lang="yabasic">roman$ = "M, CM, D, CD, C, XC, L, XL, X, IX, V, IV, I"
decml$ = "1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1"
sub toRoman$(value)
local res$, i, roman$(1), decml$(1), long
long = token(roman$, roman$(), ", ")
long = token(decml$, decml$(), ", ")
for i=1 to long
while(value >= val(decml$(i)))
res$ = res$ + roman$(i)
value = value - val(decml$(i))
wend
next i
return res$
end sub
print 400, " ", toRoman$(400)
print 1990, " ", toRoman$(1990)
print 2008, " ", toRoman$(2008)
print 2009, " ", toRoman$(2009)
print 1666, " ", toRoman$(1666)
print 3888, " ", toRoman$(3888)
//Output:
// 400 = CD
// 1990 = MCMXC
// 2008 = MMVIII
// 2009 = MMIX
// 1666 = MDCLXVI
// 3888 = MMMDCCCLXXXVIII</syntaxhighlight>
 
==={{header|ZX Spectrum Basic}}===
<syntaxhighlight lang="zxbasic"> 10 DATA 1000,"M",900,"CM"
20 DATA 500,"D",400,"CD"
30 DATA 100,"C",90,"XC"
40 DATA 50,"L",40,"XL"
50 DATA 10,"X",9,"IX"
60 DATA 5,"V",4,"IV",1,"I"
70 INPUT "Enter an arabic number: ";V
80 LET VALUE=V
90 LET V$=""
100 FOR I=0 TO 12
110 READ A,R$
120 IF V<A THEN GO TO 160
130 LET V$=V$+R$
140 LET V=V-A
150 GO TO 120
160 NEXT I
170 PRINT VALUE;"=";V$</syntaxhighlight>
 
=={{header|Batch File}}==
{{trans|BASIC}}
<syntaxhighlight lang="dos">@echo off
setlocal enabledelayedexpansion
 
set cnt=0&for %%A in (1000,900,500,400,100,90,50,40,10,9,5,4,1) do (set arab!cnt!=%%A&set /a cnt+=1)
set cnt=0&for %%R in (M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I) do (set rom!cnt!=%%R&set /a cnt+=1)
 
::Testing
call :toRoman 2009
echo 2009 = !result!
call :toRoman 1666
echo 1666 = !result!
call :toRoman 3888
echo 3888 = !result!
pause>nul
exit/b 0
 
::The "function"...
:toRoman
set value=%1
set result=
 
for /l %%i in (0,1,12) do (
set a=%%i
call :add_val
)
goto :EOF
 
:add_val
if !value! lss !arab%a%! goto :EOF
set result=!result!!rom%a%!
set /a value-=!arab%a%!
goto add_val</syntaxhighlight>
{{Out}}
<pre>2009 = MMIX
1666 = MDCLXVI
3888 = MMMDCCCLXXXVIII</pre>
 
=={{header|BCPL}}==
<syntaxhighlight lang="bcpl">get "libhdr"
 
let toroman(n, v) = valof
$( let extract(n, val, rmn, v) = valof
$( while n >= val
$( n := n - val;
for i=1 to rmn%0 do v%(v%0+i) := rmn%i
v%0 := v%0 + rmn%0
$)
resultis n
$)
v%0 := 0
n := extract(n, 1000, "M", v)
n := extract(n, 900, "CM", v)
n := extract(n, 500, "D", v)
n := extract(n, 400, "CD", v)
n := extract(n, 100, "C", v)
n := extract(n, 90, "XC", v)
n := extract(n, 50, "L", v)
n := extract(n, 40, "XL", v)
n := extract(n, 10, "X", v)
n := extract(n, 9, "IX", v)
n := extract(n, 5, "V", v)
n := extract(n, 4, "IV", v)
n := extract(n, 1, "I", v)
resultis v
$)
 
let show(n) be
$( let v = vec 50
writef("%I4 = %S*N", n, toroman(n, v))
$)
 
let start() be
$( show(1666)
show(2008)
show(1001)
show(1999)
show(3888)
show(2021)
$)</syntaxhighlight>
{{out}}
<pre>1666 = MDCLXVI
2008 = MMVIII
1001 = MI
1999 = MCMXCIX
3888 = MMMDCCCLXXXVIII
2021 = MMXXI</pre>
 
=={{header|Befunge}}==
Reads the number to convert from standard input. No range validation is performed.
 
<syntaxhighlight lang="befunge">&>0\0>00p:#v_$ >:#,_ $ @
4-v >5+#:/#<\55+%:5/\5%:
vv_$9+00g+5g\00g8+>5g\00
g>\20p>:10p00g \#v _20gv
> 2+ v^-1g01\g5+8<^ +9 _
IVXLCDM</syntaxhighlight>
 
{{out}}
<pre>1666
MDCLXVI</pre>
 
=={{header|BQN}}==
{{trans|APL}}
<syntaxhighlight lang="bqn">⟨ToRoman⇐R⟩ ← {
ds ← 1↓¨(¯1+`⊏⊸=)⊸⊔" I IV V IX X XL L XC C CD D CM M"
vs ← 1e3∾˜ ⥊1‿4‿5‿9×⌜˜10⋆↕3
R ⇐ {
𝕨𝕊0: "";
(⊑⟜ds∾·𝕊𝕩-⊑⟜vs) 1-˜⊑vs⍋𝕩
}
}</syntaxhighlight>
{{out|Example use}}
<syntaxhighlight lang="text"> ToRoman¨ 1990‿2008‿1666‿2021
⟨ "MCMXC" "MMVIII" "MDCLXVI" "MMXXI" ⟩</syntaxhighlight>
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">( ( encode
= indian roman cifr tenfoldroman letter tenfold
. !arg:#?indian
Line 498 ⟶ 2,353:
)
)
);</langsyntaxhighlight>
{{out}}
Output:
<pre>1990 MCMXC
2008 MMVIII
Line 508 ⟶ 2,363:
 
=={{header|C}}==
===Naive solution===
This solution is a smart but does not return the number written as a string.
<syntaxhighlight lang="c">#include <stdio.h>
 
<lang c>#include <stdlib.h>
#include <stdio.h>
 
int main() {
/*
int arabic[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
* Writes the Roman numeral representing n into the buffer s.
* Handles up to n = 3999.
* Since C doesn't have exceptions, n = 0 causes the whole program to exit
* unsuccessfully.
* s should be have room for at least 16 characters, including the trailing
* null.
*/
void roman(char *s, unsigned int n)
{
if (n == 0)
{
fputs(stderr, "Roman numeral for zero requested.");
exit(EXIT_FAILURE);
}
 
// There is a bug: "XL\0" is translated into sequence 58 4C 00 00, i.e. it is 4-bytes long...
#define digit(loop, num, c) \
// Should loopbe (n"XL" >=without num)\0 \etc.
//
{*(s++) = c; \
char roman[13][3] = {"M\0", "CM\0", "D\0", "CD\0", "C\0", "XC\0", "L\0", "XL\0", "X\0", "IX\0", "V\0", "IV\0", "I\0"};
n -= num;}
int N;
#define digits(loop, num, c1, c2) \
loop (n >= num) \
{*(s++) = c1; \
*(s++) = c2; \
n -= num;}
 
printf("Enter arabic number:\n");
digit ( while, 1000, 'M' )
scanf("%d", &N);
digits ( if, 900, 'C', 'M' )
printf("\nRoman number:\n");
digit ( if, 500, 'D' )
digits ( if, 400, 'C', 'D' )
digit ( while, 100, 'C' )
digits ( if, 90, 'X', 'C' )
digit ( if, 50, 'L' )
digits ( if, 40, 'X', 'L' )
digit ( while, 10, 'X' )
digits ( if, 9, 'I', 'X' )
digit ( if, 5, 'V' )
digits ( if, 4, 'I', 'V' )
digit ( while, 1, 'I' )
 
for (int i = 0; i < 13; i++) {
#undef digit
while (N >= arabic[i]) {
#undef digits
printf("%s", roman[i]);
N -= arabic[i];
*s = 0;}
}
}
return 0;
}
</syntaxhighlight>
{{out}}
<pre>Enter arabic number:
215
 
Roman number:
int main(void)
CCXV
{
</pre>
char buffer[16];
===Not thread-safe===
unsigned int i;
<syntaxhighlight lang="c">#define _CRT_SECURE_NO_WARNINGS
for (i = 1 ; i < 4000 ; ++i)
{
roman(buffer, i);
printf("%4u: %s\n", i, buffer);
}
return EXIT_SUCCESS;
}</lang>
 
#include <stdio.h>
An alternative version which builds the string backwards.
#include <string.h>
<lang c>char *ToRoman(int num, char *buf, int buflen)
 
int RomanNumerals_parseInt(const char* string)
{
int value;
static const char romanDgts[] = "ivxlcdmVXLCDM_";
return scanf("%u", &value) == 1 && value > 0 ? value : 0;
char *roman = buf + buflen;
}
int rdix, r, v;
*--roman = '\0'; /* null terminate return string */
if (num >= 4000000) {
printf("Number Too Big.\n");
return NULL;
}
for (rdix = 0; rdix < strlen(romanDgts); rdix += 2) {
if (num == 0) break;
v = (num % 10) / 5;
r = num % 5;
num = num / 10;
if (r == 4) {
if (roman < buf+2) {
printf("Buffer too small.");
return NULL;
}
*--roman = romanDgts[rdix+1+v];
*--roman = romanDgts[rdix];
}
else {
if (roman < buf+r+v) {
printf("Buffer too small.");
return NULL;
}
while(r-- > 0) {
*--roman = romanDgts[rdix];
}
if (v==1) {
*--roman = romanDgts[rdix+1];
}
}
}
return roman;
}</lang>
 
Most straightforward (nothing elegant about it, but it's simple, and can calcuate output length)
<lang C>#include <stdio.h>
 
intconst to_roman(char *out, RomanNumerals_toString(int nvalue)
{
#define ROMAN_NUMERALS_MAX_OUTPUT_STRING_SIZE 64
int len = 0;
static buffer[ROMAN_NUMERALS_MAX_OUTPUT_STRING_SIZE];
if (n <= 0) return 0; /* error indication */
# define RPUT(c) if (out) out[len] = c; len++
while(n>= 1000) { n -= 1000;RPUT('M'); };
 
const static int maxValue = 5000;
if (n >= 900) { n -= 900; RPUT('C'); RPUT('M'); };
const static int minValue = 1;
if (n >= 500) { n -= 500; RPUT('D'); };
if (n >= 400) { n -= 400; RPUT('C'); RPUT('D'); };
while (n >= 100){ n -= 100; RPUT('C'); };
 
const static struct Digit {
if (n >= 90) { n -= 90; RPUT('X'); RPUT('C'); };
ifchar (nstring[4]; >=// 50)It's better to use {4 nthan -=3 50; RPUT('L'aligment); };.
int value;
if (n >= 40) { n -= 40; RPUT('X'); RPUT('L'); };
} digits[] = {
while (n >= 10) { n -= 10; RPUT('X'); };
{"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 },
{"?", 0}
};
 
*buffer = '\0'; // faster than memset(buffer, 0, sizeof(buffer));
if (n >= 9) { n -= 9; RPUT('I'); RPUT('X'); };
if (nminValue ><= 5)value && value { n -<= 5; RPUT('V'maxValue); };
{
if (n >= 4) { n -= 4; RPUT('I'); RPUT('V'); };
whilestruct (n)Digit* digit = { n--; RPUT('I'); }&digits[0];
RPUT('\0');
# undef RPUT
 
returnwhile len;(digit->value)
{
while (value >= digit->value)
{
value -= digit->value;
// It is not necessary - total length would not be exceeded...
// if (strlen(buffer) + strlen(digit->string) < sizeof(buffer))
strcat(buffer, digit->string);
}
digit++;
}
}
return buffer;
}
 
 
int main()
int main(int argc, char* argv[])
{
if (argc < char buf[16];2)
{
int d = to_roman(buf, 1666);
// Blanks are needed for a consistient blackground on some systems.
printf("roman for 1666 is %d bytes: %s\n", d, buf);
// BTW, puts append an extra newline at the end.
//
puts("Write given numbers as Roman numerals. \n"
" \n"
"Usage: \n"
" roman n1 n2 n3 ... \n"
" \n"
"where n1 n2 n3 etc. are Arabic numerals\n");
 
int numbers[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1498, 2022 };
d = 68999123;
printffor ("%dint wouldi have= required0; %di bytes\n",< d, to_romansizeof(0,numbers) d)/ sizeof(int); i++)
{
printf("%4d = %s\n",
numbers[i], RomanNumerals_toString(numbers[i]));
}
}
else
{
for (int i = 1; i < argc; i++)
{
int number = RomanNumerals_parseInt(argv[i]);
if (number)
{
puts(RomanNumerals_toString(number));
}
else
{
puts("???");
}
}
}
 
return 0;
}</syntaxhighlight>
}</lang>Output:<pre>roman for 1666 is 8 bytes: MDCLXVI
{{Output}}
68999123 would have required 69006 bytes
<pre>Write given numbers as Roman numerals.
</pre>
 
Usage:
roman n1 n2 n3 ...
 
where n1 n2 n3 etc. are Arabic numerals
 
1 = I
2 = II
3 = III
4 = IV
5 = V
6 = VI
7 = VII
8 = VIII
9 = IX
10 = X
1498 = MCDXCVIII
2022 = MMXXII</pre>
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">using System;
class Program
{
Line 681 ⟶ 2,536:
}
}
}</langsyntaxhighlight>
 
One-liner Mono REPL
Output:
<syntaxhighlight lang="csharp">
Func<int, string> toRoman = (number) =>
new Dictionary<int, string>
{
{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"}
}.Aggregate(new string('I', number), (m, _) => m.Replace(new string('I', _.Key), _.Value));
</syntaxhighlight>
 
{{out}}
<pre>
1 = I
Line 699 ⟶ 2,575:
 
=={{header|C++}}==
===C++ 98===
<lang cpp>#include <iostream>
<syntaxhighlight lang="cpp">#include <iostream>
#include <string>
 
Line 739 ⟶ 2,616:
std::cout << to_roman(i) << std::endl;
}
}</langsyntaxhighlight>
 
===C++ 11===
<syntaxhighlight lang="cpp">#include <iostream>
#include <string>
 
std::string to_roman(int x) {
if (x <= 0)
return "Negative or zero!";
auto roman_digit = [](char one, char five, char ten, int x) {
if (x <= 3)
return std::string().assign(x, one);
if (x <= 5)
return std::string().assign(5 - x, one) + five;
if (x <= 8)
return five + std::string().assign(x - 5, one);
return std::string().assign(10 - x, one) + ten;
};
if (x >= 1000)
return x - 1000 > 0 ? "M" + to_roman(x - 1000) : "M";
if (x >= 100) {
auto s = roman_digit('C', 'D', 'M', x / 100);
return x % 100 > 0 ? s + to_roman(x % 100) : s;
}
if (x >= 10) {
auto s = roman_digit('X', 'L', 'C', x / 10);
return x % 10 > 0 ? s + to_roman(x % 10) : s;
}
return roman_digit('I', 'V', 'X', x);
}
 
int main() {
for (int i = 0; i < 2018; i++)
std::cout << i << " --> " << to_roman(i) << std::endl;
}</syntaxhighlight>
 
=={{header|Ceylon}}==
<syntaxhighlight lang="ceylon">shared void run() {
class Numeral(shared Character char, shared Integer int) {}
value tiers = [
[Numeral('I', 1), Numeral('V', 5), Numeral('X', 10)],
[Numeral('X', 10), Numeral('L', 50), Numeral('C', 100)],
[Numeral('C', 100), Numeral('D', 500), Numeral('M', 1k)]
];
String toRoman(Integer hindu, Integer tierIndex = 2) {
assert (exists tier = tiers[tierIndex]);
" Finds if it's a two character numeral like iv, ix, xl, xc, cd and cm."
function findTwoCharacterNumeral() =>
if (exists bigNum = tier.rest.find((numeral) => numeral.int - tier.first.int <= hindu < numeral.int))
then [tier.first, bigNum]
else null;
if (hindu <= 0) {
// if it's zero then we are done!
return "";
}
else if (exists [smallNum, bigNum] = findTwoCharacterNumeral()) {
value twoCharSymbol = "``smallNum.char````bigNum.char``";
value twoCharValue = bigNum.int - smallNum.int;
return "``twoCharSymbol````toRoman(hindu - twoCharValue, tierIndex)``";
}
else if (exists num = tier.reversed.find((Numeral elem) => hindu >= elem.int)) {
return "``num.char````toRoman(hindu - num.int, tierIndex)``";
}
else {
// nothing was found so move to the next smaller tier!
return toRoman(hindu, tierIndex - 1);
}
}
assert (toRoman(1) == "I");
assert (toRoman(2) == "II");
assert (toRoman(4) == "IV");
assert (toRoman(1666) == "MDCLXVI");
assert (toRoman(1990) == "MCMXC");
assert (toRoman(2008) == "MMVIII");
}</syntaxhighlight>
 
=={{header|Clojure}}==
The easiest way is to use the built-in cl-format function
<syntaxhighlight lang="clojure">(def arabic->roman
(partial clojure.pprint/cl-format nil "~@R"))
 
(arabic->roman 147)
;"CXXIII"
(arabic->roman 99)
;"XCIX"</syntaxhighlight>Alternatively:<syntaxhighlight lang="clojure">(def roman-map
(sorted-map
1 "I", 4 "IV", 5 "V", 9 "IX",
10 "X", 40 "XL", 50 "L", 90 "XC",
100 "C", 400 "CD", 500 "D", 900 "CM"
1000 "M"))
 
(defn int->roman [n]
{:pre (integer? n)}
(loop [res (StringBuilder.), n n]
(if-let [v (roman-map n)]
(str (.append res v))
(let [[k v] (->> roman-map keys (filter #(> n %)) last (find roman-map))]
(recur (.append res v) (- n k))))))
 
(int->roman 1999)
; "MCMXCIX"</syntaxhighlight>
 
 
An alternate implementation:
 
<syntaxhighlight lang="clojure">
(defn a2r [a]
(let [rv '(1000 500 100 50 10 5 1)
rm (zipmap rv "MDCLXVI")
dv (->> rv (take-nth 2) next #(interleave % %))]
(loop [a a rv rv dv dv r nil]
(if (<= a 0)
r
(let [v (first rv)
d (or (first dv) 0)
l (- v d)]
(cond
(= a v) (str r (rm v))
(= a l) (str r (rm d) (rm v))
(and (> a v) (> a l)) (recur (- a v) rv dv (str r (rm v)))
(and (< a v) (< a l)) (recur a (rest rv) (rest dv) r)
:else (recur (- a l) (rest rv) (rest dv) (str r (rm d) (rm v)))))))))
</syntaxhighlight>
 
Usage:
 
<syntaxhighlight lang="clojure">
(a2r 1666)
"MDCLXVI"
 
(map a2r [1000 1 389 45])
("M" "I" "CCCLXXXIX" "XLV")
</syntaxhighlight>
 
An alternate implementation:
 
<syntaxhighlight lang="clojure">
(def roman-map
(sorted-map-by >
1 "I", 4 "IV", 5 "V", 9 "IX",
10 "X", 40 "XL", 50 "L", 90 "XC",
100 "C", 400 "CD", 500 "D", 900 "CM"
1000 "M"))
 
(defn a2r
([r]
(reduce str (a2r r (keys roman-map))))
([r n]
(when-not (empty? n)
(let [e (first n)
v (- r e)
roman (roman-map e)]
(cond
(< v 0) (a2r r (rest n))
(= v 0) (cons roman [])
(>= v e) (cons roman (a2r v n))
(< v e) (cons roman (a2r v (rest n))))))))
</syntaxhighlight>
 
Usage:
 
<syntaxhighlight lang="clojure">
(a2r 1666)
"MDCLXVI"
 
(map a2r [1000 1 389 45])
("M" "I" "CCCLXXXIX" "XLV")
</syntaxhighlight>
 
=={{header|CLU}}==
<syntaxhighlight lang="clu">roman = cluster is encode
rep = null
dmap = struct[v: int, s: string]
darr = array[dmap]
own chunks: darr := darr$
[dmap${v: 1000, s: "M"},
dmap${v: 900, s: "CM"},
dmap${v: 500, s: "D"},
dmap${v: 400, s: "CD"},
dmap${v: 100, s: "C"},
dmap${v: 90, s: "XC"},
dmap${v: 50, s: "L"},
dmap${v: 40, s: "XL"},
dmap${v: 10, s: "X"},
dmap${v: 9, s: "IX"},
dmap${v: 5, s: "V"},
dmap${v: 4, s: "IV"},
dmap${v: 1, s: "I"}]
largest_chunk = proc (i: int) returns (int, string)
for chunk: dmap in darr$elements(chunks) do
if chunk.v <= i then return (chunk.v, chunk.s) end
end
return (0, "")
end largest_chunk
encode = proc (i: int) returns (string)
result: string := ""
while i > 0 do
val: int chunk: string
val, chunk := largest_chunk(i)
result := result || chunk
i := i - val
end
return (result)
end encode
end roman
 
start_up = proc ()
po: stream := stream$primary_output()
tests: array[int] := array[int]$[1666, 2008, 1001, 1999, 3888, 2021]
for test: int in array[int]$elements(tests) do
stream$putl(po, int$unparse(test) || " = " || roman$encode(test))
end
end start_up</syntaxhighlight>
{{out}}
<pre>1666 = MDCLXVI
2008 = MMVIII
1001 = MI
1999 = MCMXCIX
3888 = MMMDCCCLXXXVIII
2021 = MMXXI</pre>
 
=={{header|COBOL}}==
 
<syntaxhighlight lang="cobol">
<lang COBOL>
IDENTIFICATION DIVISION.
PROGRAM-ID. TOROMAN.
Line 796 ⟶ 2,904:
end-perform
.
</syntaxhighlight>
</lang>
{{out}} (input was supplied via STDIN)
<p>Output:
(input was supplied via STDIN)
</p>
<pre>
inp=0111 roman=CXI
Line 818 ⟶ 2,924:
=={{header|CoffeeScript}}==
 
<langsyntaxhighlight lang="coffeescript">
decimal_to_roman = (n) ->
# This should work for any positive integer, although it
Line 865 ⟶ 2,971:
else
console.log "error for #{decimal}: #{roman} is wrong"
</syntaxhighlight>
</lang>
 
=={{header|Common Lisp}}==
 
<langsyntaxhighlight lang="lisp">(defun roman-numeral (n)
(format nil "~@R" n))</langsyntaxhighlight>
 
=={{header|ClojureCowgol}}==
<syntaxhighlight lang="cowgol">include "cowgol.coh";
The easiest way is to use the built-in cl-format function
include "argv.coh";
<lang Clojure>
(def arabic->roman
(partial clojure.pprint/cl-format nil "~@R"))
 
# Encode the given number as a Roman numeral
(arabic->roman 147)
sub decimalToRoman(num: uint16, buf: [uint8]): (rslt: [uint8]) is
;"CXXIII"
# return the start of the buffer for easy printing
(arabic->roman 99)
rslt := buf;
;"XCIX"
# Add string to buffer
sub Add(str: [uint8]) is
while [str] != 0 loop
[buf] := [str];
buf := @next buf;
str := @next str;
end loop;
end sub;
# Table of Roman numerals
record Roman is
value: uint16;
string: [uint8];
end record;
var numerals: Roman[] := {
{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 curNum := &numerals as [Roman];
while num != 0 loop
while num >= curNum.value loop
Add(curNum.string);
num := num - curNum.value;
end loop;
curNum := @next curNum;
end loop;
[buf] := 0; # terminate the string
end sub;
 
# Read numbers from the command line and print the corresponding Roman numerals
</lang>
ArgvInit();
var buffer: uint8[100];
loop
var argmt := ArgvNext();
if argmt == (0 as [uint8]) then
break;
end if;
var dummy: [uint8];
var number: int32;
(number, dummy) := AToI(argmt);
print(decimalToRoman(number as uint16, &buffer as [uint8]));
print_nl();
end loop;</syntaxhighlight>
 
{{out}}
Alternatively
 
<pre>$ ./romanenc.386 1990 2008 1666
<lang Clojure>
MCMXC
(def arabic-roman-map
MMVIII
{1 "I", 5 "V",
MDCLXVI</pre>
10 "X", 50 "L",
100 "C", 500 "D",
1000 "M",
4 "IV", 9 "IX",
40 "XL", 90 "XC",
400 "CD", 900 "CM" })
 
(def arabic-roman-map-sorted-keys
(sort (keys arabic-roman-map)))
 
(defn find-value-in-coll
[coll k]
(let [aval (find coll k)]
(if (nil? aval) "" (val aval))))
 
(defn to-roman
[result n]
(let
[closest-key-for-n (last (filter #(> n %) arabic-roman-map-sorted-keys))
roman-value-for-n (find-value-in-coll arabic-roman-map n)
roman-value-for-closet-to-n (find-value-in-coll arabic-roman-map
closest-key-for-n)]
(if (or (<= n 0)(contains? arabic-roman-map n))
(conj result roman-value-for-n)
(recur (conj result roman-value-for-closet-to-n)
(- n closest-key-for-n)))))
 
Usage: >(to-roman [] 1999)
result: ["M" "CM" "XC" "IX"]
 
</lang>
 
 
An alternate implementation:
 
<lang Clojure>
(defn a2r
[a]
(let [rv [1000 500 100 50 10 5 1]
rm (zipmap rv "MDCLXVI")
dv (->> rv (take-nth 2) next (#(interleave % %)))]
(loop [a a rv rv dv dv r nil]
(if (<= a 0)
r
(let [v (first rv)
d (or (first dv) 0)
l (- v d)]
(cond
(= a v) (str r (rm v))
(= a l) (str r (rm d) (rm v))
(and (> a v) (> a l)) (recur (- a v) rv dv (str r (rm v)))
(and (< a v) (< a l)) (recur a (rest rv) (rest dv) r)
:else (recur (- a l) (rest rv) (rest dv) (str r (rm d) (rm v)))))))))
</lang>
 
Usage:
 
<lang Clojure>
(a2r 1666)
"MDCLXVI"
 
(map a2r [1000 1 389 45])
("M" "I" "CCCLXXXIX" "XLV")
</lang>
 
=={{header|D}}==
<langsyntaxhighlight lang="d">string toRoman(int n) pure nothrow
in {
assert(n < 5000);
Line 981 ⟶ 3,071:
}
 
void main() {}</langsyntaxhighlight>
 
=={{header|Delphi}}==
{{trans|DWScript}}
<langsyntaxhighlight lang="delphi">program RomanNumeralsEncode;
 
{$APPTYPE CONSOLE}
Line 1,012 ⟶ 3,102:
Writeln(IntegerToRoman(2008)); // MMVIII
Writeln(IntegerToRoman(1666)); // MDCLXVI
end.</langsyntaxhighlight>
 
=={{header|DWScript}}==
{{trans|D}}
<langsyntaxhighlight lang="delphi">const weights = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
const symbols = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
 
Line 1,035 ⟶ 3,125:
PrintLn(toRoman(455));
PrintLn(toRoman(3456));
PrintLn(toRoman(2488));</langsyntaxhighlight>
 
=={{header|EasyLang}}==
 
<syntaxhighlight lang="text">
func$ dec2rom dec .
values[] = [ 1000 900 500 400 100 90 50 40 10 9 5 4 1 ]
symbol$[] = [ "M" "CM" "D" "CD" "C" "XC" "L" "XL" "X" "IX" "V" "IV" "I" ]
for i = 1 to len values[]
while dec >= values[i]
rom$ &= symbol$[i]
dec -= values[i]
.
.
return rom$
.
print dec2rom 1990
print dec2rom 2008
print dec2rom 1666
</syntaxhighlight>
 
=={{header|ECL}}==
<langsyntaxhighlight ECLlang="ecl">RomanEncode(UNSIGNED Int) := FUNCTION
SetWeights := [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
SetSymbols := ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
Line 1,062 ⟶ 3,171:
RomanEncode(1990 ); //MCMXC
RomanEncode(2008 ); //MMVIII
RomanEncode(1666); //MDCLXVI</langsyntaxhighlight>
 
=={{header|Eiffel}}==
<syntaxhighlight lang="eiffel">class
APPLICATION
 
create
make
 
feature {NONE} -- Initialization
 
make
local
numbers: ARRAY [INTEGER]
do
numbers := <<1990, 2008, 1666, 3159, 1977, 2010>>
-- "MCMXC", "MMVIII", "MDCLXVI", "MMMCLIX", "MCMLXXVII", "MMX"
across numbers as n loop
print (n.item.out + " in decimal Arabic numerals is " +
decimal_to_roman (n.item) + " in Roman numerals.%N")
end
end
 
feature -- Roman numerals
 
decimal_to_roman (a_int: INTEGER): STRING
-- Representation of integer `a_int' as Roman numeral
require
a_int > 0
local
dnums: ARRAY[INTEGER]
rnums: ARRAY[STRING]
 
dnum: INTEGER
rnum: STRING
 
i: INTEGER
do
dnums := <<1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1>>
rnums := <<"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I">>
 
dnum := a_int
rnum := ""
 
from
i := 1
until
i > dnums.count or dnum <= 0
loop
from
until
dnum < dnums[i]
loop
dnum := dnum - dnums[i]
rnum := rnum + rnums[i]
end
i := i + 1
end
 
Result := rnum
end
end</syntaxhighlight>
 
=={{header|Ela}}==
{{trans|Haskell}}
<syntaxhighlight lang="ela">open number string math
 
digit x y z k =
[[x],[x,x],[x,x,x],[x,y],[y],[y,x],[y,x,x],[y,x,x,x],[x,z]] :
(toInt k - 1)
toRoman 0 = ""
toRoman x | x < 0 = fail "Negative roman numeral"
| x >= 1000 = 'M' :: toRoman (x - 1000)
| x >= 100 = let (q,r) = x `divrem` 100 in
digit 'C' 'D' 'M' q ++ toRoman r
| x >= 10 = let (q,r) = x `divrem` 10 in
digit 'X' 'L' 'C' q ++ toRoman r
| else = digit 'I' 'V' 'X' x
 
map (join "" << toRoman) [1999,25,944]</syntaxhighlight>
 
{{out}}
<pre>["MCMXCIX","XXV","CMXLIV"]</pre>
 
=={{header|Elena}}==
{{trans|C#}}
ELENA 6.x :
<syntaxhighlight lang="elena">import system'collections;
import system'routines;
import extensions;
import extensions'text;
static RomanDictionary = Dictionary.new()
.setAt(1000, "M")
.setAt(900, "CM")
.setAt(500, "D")
.setAt(400, "CD")
.setAt(100, "C")
.setAt(90, "XC")
.setAt(50, "L")
.setAt(40, "XL")
.setAt(10, "X")
.setAt(9, "IX")
.setAt(5, "V")
.setAt(4, "IV")
.setAt(1, "I");
extension op
{
toRoman()
= RomanDictionary.accumulate(new StringWriter("I", self), (m,kv => m.replace(new StringWriter("I",kv.Key).Value, kv.Value)));
}
public program()
{
console.printLine("1990 : ", 1990.toRoman());
console.printLine("2008 : ", 2008.toRoman());
console.printLine("1666 : ", 1666.toRoman())
}</syntaxhighlight>
{{out}}
<pre>
1990 : MCMXC
2008 : MMVIII
1666 : MDCLXVI
</pre>
 
=={{header|Elixir}}==
{{trans|Erlang}}
<syntaxhighlight lang="elixir">defmodule Roman_numeral do
def encode(0), do: ''
def encode(x) when x >= 1000, do: [?M | encode(x - 1000)]
def encode(x) when x >= 100, do: digit(div(x,100), ?C, ?D, ?M) ++ encode(rem(x,100))
def encode(x) when x >= 10, do: digit(div(x,10), ?X, ?L, ?C) ++ encode(rem(x,10))
def encode(x) when x >= 1, do: digit(x, ?I, ?V, ?X)
defp digit(1, x, _, _), do: [x]
defp digit(2, x, _, _), do: [x, x]
defp digit(3, x, _, _), do: [x, x, x]
defp digit(4, x, y, _), do: [x, y]
defp digit(5, _, y, _), do: [y]
defp digit(6, x, y, _), do: [y, x]
defp digit(7, x, y, _), do: [y, x, x]
defp digit(8, x, y, _), do: [y, x, x, x]
defp digit(9, x, _, z), do: [x, z]
end</syntaxhighlight>
 
'''Another:'''
{{trans|Ruby}}
<syntaxhighlight lang="elixir">defmodule Roman_numeral do
@symbols [ {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'} ]
def encode(num) do
{roman,_} = Enum.reduce(@symbols, {[], num}, fn {divisor, letter}, {memo, n} ->
{memo ++ List.duplicate(letter, div(n, divisor)), rem(n, divisor)}
end)
Enum.join(roman)
end
end</syntaxhighlight>
 
'''Test:'''
<syntaxhighlight lang="elixir">Enum.each([1990, 2008, 1666], fn n ->
IO.puts "#{n}: #{Roman_numeral.encode(n)}"
end)</syntaxhighlight>
 
{{out}}
<pre>
1990: MCMXC
2008: MMVIII
1666: MDCLXVI
</pre>
 
=={{header|Emacs Lisp}}==
<syntaxhighlight lang="lisp">(defun ar2ro (AN)
<lang lisp>
"Translate from arabic number AN to roman number.
(defun ar2ro (AN)
For example, (ar2ro 1666) returns (M D C L X V I)."
"translate from arabic number AN to roman number,
ar2ro(1666) returns (M D C L X V I)"
(cond
((>= AN 1000) (cons 'M (ar2ro (- AN 1000))))
((>= AN 900) (cons 'C (cons 'M (ar2ro (- AN 900)))))
((>= AN 500) (cons 'D (ar2ro (- AN 500))))
((>= AN 400) (cons 'C (cons 'D (ar2ro (- AN 400)))))
Line 1,082 ⟶ 3,360:
((>= AN 4) (cons 'I (cons 'V (ar2ro (- AN 4)))))
((>= AN 1) (cons 'I (ar2ro (- AN 1))))
((= AN 0) nil)))</syntaxhighlight>
 
</lang>
=={{header|Erlang}}==
{{trans|OCaml}}
<langsyntaxhighlight lang="erlang">-module(roman).
-export([to_roman/1]).
 
Line 1,105 ⟶ 3,383:
digit(7, X, Y, _) -> [Y, X, X];
digit(8, X, Y, _) -> [Y, X, X, X];
digit(9, X, _, Z) -> [X, Z].</langsyntaxhighlight>
 
sample:
Line 1,120 ⟶ 3,398:
 
Alternative:
<langsyntaxhighlight lang="erlang">
-module( roman_numerals ).
 
Line 1,141 ⟶ 3,419:
map() -> [{"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}].
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,152 ⟶ 3,430:
"MDCLXVI"
</pre>
 
=={{header|ERRE}}==
<syntaxhighlight lang="erre">
PROGRAM ARAB2ROMAN
 
DIM ARABIC%[12],ROMAN$[12]
 
PROCEDURE TOROMAN(VALUE->ANS$)
LOCAL RESULT$
FOR I%=0 TO 12 DO
WHILE VALUE>=ARABIC%[I%] DO
RESULT$+=ROMAN$[I%]
VALUE-=ARABIC%[I%]
END WHILE
END FOR
ANS$=RESULT$
END PROCEDURE
 
BEGIN
!
!Testing
!
ARABIC%[]=(1000,900,500,400,100,90,50,40,10,9,5,4,1)
ROMAN$[]=("M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I")
TOROMAN(2009->ANS$) PRINT("2009 = ";ANS$)
TOROMAN(1666->ANS$) PRINT("1666 = ";ANS$)
TOROMAN(3888->ANS$) PRINT("3888 = ";ANS$)
END PROGRAM
</syntaxhighlight>
 
=={{header|Euphoria}}==
{{trans|BASIC}}
<langsyntaxhighlight Euphorialang="euphoria">constant arabic = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }
constant roman = {"M", "CM", "D","CD", "C","XC","L","XL","X","IX","V","IV","I"}
 
Line 1,172 ⟶ 3,479:
printf(1,"%d = %s\n",{2009,toRoman(2009)})
printf(1,"%d = %s\n",{1666,toRoman(1666)})
printf(1,"%d = %s\n",{3888,toRoman(3888)})</langsyntaxhighlight>
 
{{out}}
Output:
<pre>
2009 = MMIX
1666 = MDCLXVI
3888 = MMMDCCCLXXXVIII
</pre>
 
 
=={{header|Excel}}==
Excel can encode numbers in Roman forms in 5 successively concise forms. These can be indicated from 0 to 4. Type in a cell:
These can be indicated from 0 to 4. Type in a cell:
<lang Excel>
<syntaxhighlight lang="excel">
=ROMAN(2013,0)
</syntaxhighlight>
</lang>
 
It becomes:
<syntaxhighlight lang="text">
MMXIII
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">let digit x y z = function
1 -> x
| 2 -> x + x
Line 1,219 ⟶ 3,528:
|> List.map (fun n -> roman n)
|> List.iter (printfn "%s")
0</langsyntaxhighlight>
{{out}}
Output
<pre>MCMXC
MMVIII
Line 1,227 ⟶ 3,536:
=={{header|Factor}}==
A roman numeral library ships with Factor.
<langsyntaxhighlight lang="factor">USE: roman
( scratchpad ) 3333 >roman .
"mmmcccxxxiii"</langsyntaxhighlight>
 
Parts of the implementation:
 
<langsyntaxhighlight lang="factor">CONSTANT: roman-digits
{ "m" "cm" "d" "cd" "c" "xc" "l" "xl" "x" "ix" "v" "iv" "i" }
 
Line 1,248 ⟶ 3,557:
roman-values roman-digits [
[ /mod swap ] dip <repetition> concat
] 2map "" concat-as nip ;</langsyntaxhighlight>
 
=={{header|FALSE}}==
<langsyntaxhighlight lang="false">^$." "
[$999>][1000- "M"]#
$899> [ 900-"CM"]?
Line 1,264 ⟶ 3,573:
$ 4> [ 5- "V"]?
$ 3> [ 4-"IV"]?
[$ ][ 1- "I"]#%</langsyntaxhighlight>
 
=={{header|Fan}}==
<syntaxhighlight lang="fan">**
<lang Fan>**
** converts a number to its roman numeral representation
**
Line 1,304 ⟶ 3,613:
}
 
}</langsyntaxhighlight>
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">: vector create ( n -- ) 0 do , loop does> ( n -- ) swap cells + @ execute ;
\ these are ( numerals -- numerals )
: ,I dup c@ C, ; : ,V dup 1 + c@ C, ; : ,X dup 2 + c@ C, ;
Line 1,324 ⟶ 3,633:
1999 roman type \ MCMXCIX
25 roman type \ XXV
944 roman type \ CMXLIV</langsyntaxhighlight>
Alternative implementation
<langsyntaxhighlight lang="forth">create romans 0 , 1 , 5 , 21 , 9 , 2 , 6 , 22 , 86 , 13 ,
does> swap cells + @ ;
 
Line 1,344 ⟶ 3,653:
create (roman) 16 chars allot
 
1999 (roman) >roman type cr</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
<langsyntaxhighlight lang="fortran">program roman_numerals
 
implicit none
Line 1,382 ⟶ 3,691:
end function roman
 
end program roman_numerals</langsyntaxhighlight>
{{out}}
Output:
<pre>
MMIX
MDCLXVI
MMMDCCCLXXXVIII
</pre>
 
=={{header|Go}}==
For fluff, the unicode overbar is recognized as a factor of 1000, [http://en.wikipedia.org/wiki/Roman_numerals#Large_numbers as described in WP].
 
If you see boxes in the code below, those are supposed to be the Unicode combining overline (U+0305) and look like {{overline|IVXLCDM}}. Or, if you see overstruck combinations of letters, that's a different font rendering problem. (If you need roman numerals > 3999 reliably, it might best to stick to chiseling them in stone...)
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 1,430 ⟶ 3,742:
}
}
}</langsyntaxhighlight>
{{out}}
Output:
<pre>
1990 == MCMXC
Line 1,437 ⟶ 3,749:
1666 == MDCLXVI
</pre>
 
=={{header|Golo}}==
<syntaxhighlight lang="golo">#!/usr/bin/env golosh
----
This module takes a decimal integer and converts it to a Roman numeral.
----
module Romannumeralsencode
 
augment java.lang.Integer {
 
function digits = |this| {
 
var remaining = this
let digits = vector[]
while remaining > 0 {
digits: prepend(remaining % 10)
remaining = remaining / 10
}
return digits
}
 
----
123: digitsWithPowers() will return [[1, 2], [2, 1], [3, 0]]
----
function digitsWithPowers = |this| -> vector[
[ this: digits(): get(i), (this: digits(): size() - 1) - i ] for (var i = 0, i < this: digits(): size(), i = i + 1)
]
 
function encode = |this| {
 
require(this > 0, "the integer must be positive!")
 
let romanPattern = |digit, powerOf10| -> match {
when digit == 1 then i
when digit == 2 then i + i
when digit == 3 then i + i + i
when digit == 4 then i + v
when digit == 5 then v
when digit == 6 then v + i
when digit == 7 then v + i + i
when digit == 8 then v + i + i + i
when digit == 9 then i + x
otherwise ""
} with {
i, v, x = [
[ "I", "V", "X" ],
[ "X", "L", "C" ],
[ "C", "D", "M" ],
[ "M", "?", "?" ]
]: get(powerOf10)
}
 
return vector[ romanPattern(digit, power) foreach digit, power in this: digitsWithPowers() ]: join("")
}
}
 
function main = |args| {
println("1990 == MCMXC? " + (1990: encode() == "MCMXC"))
println("2008 == MMVIII? " + (2008: encode() == "MMVIII"))
println("1666 == MDCLXVI? " + (1666: encode() == "MDCLXVI"))
}</syntaxhighlight>
 
=={{header|Groovy}}==
<langsyntaxhighlight lang="groovy">symbols = [ 1:'I', 4:'IV', 5:'V', 9:'IX', 10:'X', 40:'XL', 50:'L', 90:'XC', 100:'C', 400:'CD', 500:'D', 900:'CM', 1000:'M' ]
 
def roman(arabic) {
Line 1,466 ⟶ 3,839:
assert roman(1666) == 'MDCLXVI'
assert roman(1990) == 'MCMXC'
assert roman(2008) == 'MMVIII'</langsyntaxhighlight>
 
=={{header|Haskell}}==
Line 1,472 ⟶ 3,845:
With an explicit decimal digit representation list:
 
<langsyntaxhighlight lang="haskell">digit x:: yChar z-> kChar =-> Char -> Integer -> String
digit x y z k =
[[x],[x,x],[x,x,x],[x,y],[y],[y,x],[y,x,x],[y,x,x,x],[x,z]] !!
[[x], [x, x], [x, x, x], [x, y], [y], [y, x], [y, x, x], [y, x, x, x], [x, z]] !!
(fromInteger k - 1)
 
toRoman :: Integer -> String
toRoman 0 = ""
toRoman x
toRoman x | x < 0 = error "Negative roman numeral"
toRoman x | x >=< 10000 = 'M'error : toRoman (x"Negative -roman 1000)numeral"
toRoman x
toRoman x | x >= 100 = digit 'C' 'D' 'M' q ++ toRoman r where
| x >= 1000 = 'M' : toRoman (x - 1000)
(q,r) = x `divMod` 100
toRoman x
toRoman x | x >= 10 = digit 'X' 'L' 'C' q ++ toRoman r where
| x >= 100 = digit 'C' 'D' 'M' q ++ toRoman r
(q,r) = x `divMod` 10
where
toRoman x = digit 'I' 'V' 'X' x</lang>
(q, r) = x `divMod` 100
toRoman x
| x >= 10 = digit 'X' 'L' 'C' q ++ toRoman r
where
(q, r) = x `divMod` 10
toRoman x = digit 'I' 'V' 'X' x
 
main :: IO ()
Output:
main = print $ toRoman <$> [1999, 25, 944]</syntaxhighlight>
{{out}}
<pre>["MCMXCIX","XXV","CMXLIV"]</pre>
 
or, defining '''romanFromInt''' in terms of mapAccumL
<lang haskell>*Main> map toRoman [1999,25,944]
 
["MCMXCIX","XXV","CMXLIV"]</lang>
<syntaxhighlight lang="haskell">import Data.Bifunctor (first)
import Data.List (mapAccumL)
import Data.Tuple (swap)
 
roman :: Int -> String
roman =
romanFromInt $
zip
[1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
(words "M CM D CD C XC L XL X IX V IV I")
 
romanFromInt :: [(Int, String)] -> Int -> String
romanFromInt nks n = concat . snd $ mapAccumL go n nks
where
go a (v, s) = swap $ first ((>> s) . enumFromTo 1) $ quotRem a v
 
main :: IO ()
main = (putStrLn . unlines) (roman <$> [1666, 1990, 2008, 2016, 2018])</syntaxhighlight>
{{Out}}
<pre>MDCLXVI
MCMXC
MMVIII
MMXVI
MMXVIII</pre>
 
With the Roman patterns abstracted, and in a simple logic programming idiom:
 
<syntaxhighlight lang="haskell">
module Main where
 
------------------------
-- ENCODER FUNCTION --
------------------------
 
romanDigits = "IVXLCDM"
 
-- Meaning and indices of the romanDigits sequence:
--
-- magnitude | 1 5 | index
-- -----------|-------|-------
-- 0 | I V | 0 1
-- 1 | X L | 2 3
-- 2 | C D | 4 5
-- 3 | M | 6
--
-- romanPatterns are index offsets into romanDigits,
-- from an index base of 2 * magnitude.
 
romanPattern 0 = [] -- empty string
romanPattern 1 = [0] -- I or X or C or M
romanPattern 2 = [0,0] -- II or XX...
romanPattern 3 = [0,0,0] -- III...
romanPattern 4 = [0,1] -- IV...
romanPattern 5 = [1] -- ...
romanPattern 6 = [1,0]
romanPattern 7 = [1,0,0]
romanPattern 8 = [1,0,0,0]
romanPattern 9 = [0,2]
 
encodeValue 0 _ = ""
encodeValue value magnitude = encodeValue rest (magnitude + 1) ++ digits
where
low = rem value 10 -- least significant digit (encoded now)
rest = div value 10 -- the other digits (to be encoded next)
indices = map addBase (romanPattern low)
addBase i = i + (2 * magnitude)
digits = map pickDigit indices
pickDigit i = romanDigits!!i
 
encode value = encodeValue value 0
 
------------------
-- TEST SUITE --
------------------
 
main = do
test "MCMXC" 1990
test "MMVIII" 2008
test "MDCLXVI" 1666
 
test expected value = putStrLn ((show value) ++ " = " ++ roman ++ remark)
where
roman = encode value
remark =
" (" ++
(if roman == expected then "PASS"
else ("FAIL, expected " ++ (show expected))) ++ ")"
</syntaxhighlight>
{{out}}
<pre>
1990 = MCMXC (PASS)
2008 = MMVIII (PASS)
1666 = MDCLXVI (PASS)
</pre>
 
=={{header|HicEst}}==
<langsyntaxhighlight lang="hicest">CHARACTER Roman*20
 
CALL RomanNumeral(1990, Roman) ! MCMXC
Line 1,513 ⟶ 3,990:
ENDDO
ENDDO
END</langsyntaxhighlight>
 
=={{header|Hoon}}==
 
Library file (e.g. <code>/lib/rhonda.hoon</code>):
 
<syntaxhighlight lang="hoon">|%
++ parse
|= t=tape ^- @ud
=. t (cass t)
=| result=@ud
|-
?~ t result
?~ t.t (add result (from-numeral i.t))
=+ [a=(from-numeral i.t) b=(from-numeral i.t.t)]
?: (gte a b) $(result (add result a), t t.t)
$(result (sub (add result b) a), t t.t.t)
++ yield
|= n=@ud ^- tape
=| result=tape
=/ values to-numeral
|-
?~ values result
?: (gte n -.i.values)
$(result (weld result +.i.values), n (sub n -.i.values))
$(values t.values)
++ from-numeral
|= c=@t ^- @ud
?: =(c 'i') 1
?: =(c 'v') 5
?: =(c 'x') 10
?: =(c 'l') 50
?: =(c 'c') 100
?: =(c 'd') 500
?: =(c 'm') 1.000
!!
++ to-numeral
^- (list [@ud tape])
:*
[1.000 "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"]
~
==
--</syntaxhighlight>
 
Script file ("generator") (e.g. <code>/gen/roman.hoon</code>):
 
<syntaxhighlight lang="hoon">/+ *roman
:- %say
|= [* [x=$%([%from-roman tape] [%to-roman @ud]) ~] ~]
:- %noun
^- tape
?- -.x
%from-roman "{<(parse +.x)>}"
%to-roman (yield +.x)
==</syntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">link numbers # commas, roman
 
procedure main(arglist)
every x := !arglist do
write(commas(x), " -> ",roman(x)|"*** can't convert to Roman numerals ***")
end</langsyntaxhighlight>
 
{{libheader|Icon Programming Library}}
[http://www.cs.arizona.edu/icon/library/src/procs/numbers.icn numbers.icn provides roman] as seen below and is based upon a James Gimple SNOBOL4 function.
 
<langsyntaxhighlight Iconlang="icon">procedure roman(n) #: convert integer to Roman numeral
local arabic, result
static equiv
Line 1,536 ⟶ 4,080:
result := map(result,"IVXLCDM","XLCDM**") || equiv[arabic + 1]
if find("*",result) then fail else return result
end</langsyntaxhighlight>
 
{{out}}
Sample output:
<pre>#roman.exe 3 4 8 49 2010 1666 3000 3999 4000
 
Line 1,549 ⟶ 4,093:
3,999 -> MMMCMXCIX
4,000 -> *** can't convert to Roman numerals ***</pre>
 
=={{header|Intercal}}==
INTERCAL outputs numbers as Roman numerals by default, so this is surprisingly trivial for a language that generally tries to make things as difficult as possible. Although you do still have to <i>input</i> the numbers as spelled out digitwise in all caps.
 
<syntaxhighlight lang="intercal"> PLEASE WRITE IN .1
DO READ OUT .1
DO GIVE UP</syntaxhighlight>
 
{{Out}}
<pre>$ ./roman
ONE SIX SIX SIX
MDCLXVI
 
</pre>
 
=={{header|Io}}==
 
{{trans|C#}}
<langsyntaxhighlight Iolang="io">Roman := Object clone do (
nums := list(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
rum := list("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I")
Line 1,570 ⟶ 4,129:
)
 
Roman numeral(1666) println</langsyntaxhighlight>
 
=={{header|J}}==
<tt>rfd</tt> obtains Roman numerals from decimals.
 
<langsyntaxhighlight lang="j">R1000=. ;L:1 ,{ <@(<;._1);._2]0 :0
C CC CCC CD D DC DCC DCCC CM
X XX XXX XL L LX LXX LXXX XC
Line 1,581 ⟶ 4,140:
)
 
rfd=: ('M' $~ <.@%&1000) , R1000 {::~ 1000&|</langsyntaxhighlight>
 
Explanation: R1000's definition contains rows representing each of 10 different digits in the 100s, 10s and 1s column (the first entry in each row is blank -- each entry is preceded by a space). R1000 itself represents the first 1000 roman numerals (the cartesian product of these three rows of roman numeral "digits" which is constructed so that they are in numeric order. And the first entry -- zero -- is just blank). To convert a number to its roman numeral representation, we will separate the number into the integer part after dividing by 1000 (that's the number of 'M's we need) and the remainder after dividing by 1000 (which will be an index into R1000).
 
For example:<langsyntaxhighlight lang="j"> rfd 1234
MCCXXXIV
rfd 567
DLXVII
rfd 89
LXXXIX</langsyntaxhighlight>
 
Derived from the [[j:Essays/Roman Numerals|J Wiki]]. Further examples of use will be found there.
Line 1,599 ⟶ 4,158:
The conversion function throws an IllegalArgumentException for non-positive numbers, since Java does not have unsigned primitives.
{{works with|Java|1.5+}}
<langsyntaxhighlight lang="java5">public class RN {
 
enum Numeral {
Line 1,639 ⟶ 4,198:
}
 
}</langsyntaxhighlight>
{{out}}
Output:
<pre>1999 = MCMXCIX
25 = XXV
Line 1,649 ⟶ 4,208:
at RN.main(RN.java:38)</pre>
{{works with|Java|1.8+}}
<langsyntaxhighlight lang="java5">import java.util.Set;
import java.util.EnumSet;
import java.util.Collections;
Line 1,707 ⟶ 4,266:
LongStream.of(1999, 25, 944).forEach(RomanNumerals::test);
}
}</langsyntaxhighlight>
{{out}}
Output:
<pre>1999 = MCMXCIX
MCMXCIX = 1999
Line 1,717 ⟶ 4,276:
 
=={{header|JavaScript}}==
 
===ES5===
====Iteration====
 
{{trans|Tcl}}
<langsyntaxhighlight lang="javascript">var roman = {
map: [
1000, 'M', 900, 'CM', 500, 'D', 400, 'CD', 100, 'C', 90, 'XC',
Line 1,735 ⟶ 4,298:
}
 
roman.int_to_roman(1999); // "MCMXCIX"</langsyntaxhighlight>
 
====Functional composition====
=={{header|LaTeX}}==
The macro <code>\Roman</code> is defined for uppercase roman numeral, accepting as ''argument'' a name of an existing counter.
 
<syntaxhighlight lang="javascript">(function () {
<lang latex>\documentclass{article}
'use strict';
\begin{document}
\newcounter{currentyear}\setcounter{currentyear}{\year}
Anno Domini \Roman{currentyear}
\end{document}</lang>
 
=={{header|Liberty BASIC}}==
<lang lb>
dim arabic( 12)
for i =0 to 12
read k
arabic( i) =k
next i
data 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
 
// If the Roman is a string, pass any delimiters through
dim roman$( 12)
for i =0 to 12
read k$
roman$( i) =k$
next i
data "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
 
// (Int | String) -> String
print 2009, toRoman$( 2009)
function romanTranscription(a) {
print 1666, toRoman$( 1666)
if (typeof a === 'string') {
print 3888, toRoman$( 3888)
var ps = a.split(/\d+/),
dlm = ps.length > 1 ? ps[1] : undefined;
 
return (dlm ? a.split(dlm)
.map(function (x) {
return Number(x);
}) : [a])
.map(roman)
.join(dlm);
} else return roman(a);
}
 
// roman :: Int -> String
function roman(n) {
return [[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"]]
.reduce(function (a, lstPair) {
var m = a.remainder,
v = lstPair[0];
 
return (v > m ? a : {
remainder: m % v,
roman: a.roman + Array(
Math.floor(m / v) + 1
)
.join(lstPair[1])
});
}, {
remainder: n,
roman: ''
}).roman;
}
 
// TEST
 
return [2016, 1990, 2008, "14.09.2015", 2000, 1666].map(
romanTranscription);
 
})();</syntaxhighlight>
 
{{Out}}
<syntaxhighlight lang="javascript">["MMXVI", "MCMXC", "MMVIII", "XIV.IX.MMXV", "MM", "MDCLXVI"]</syntaxhighlight>
 
===ES6===
====Functional====
{{Trans|Haskell}}
(mapAccumL version)
<syntaxhighlight lang="javascript">(() => {
"use strict";
 
// -------------- ROMAN INTEGER STRINGS --------------
 
// roman :: Int -> String
const roman = n =>
mapAccumL(residue =>
([k, v]) => second(
q => 0 < q ? (
k.repeat(q)
) : ""
)(remQuot(residue)(v))
)(n)(
zip([
"M", "CM", "D", "CD", "C", "XC",
"L", "XL", "X", "IX", "V", "IV", "I"
])([
1000, 900, 500, 400, 100, 90,
50, 40, 10, 9, 5, 4, 1
])
)[1]
.join("");
 
 
// ---------------------- TEST -----------------------
// main :: IO ()
const main = () => (
[2016, 1990, 2008, 2000, 2020, 1666].map(roman)
).join("\n");
 
 
// ---------------- GENERIC FUNCTIONS ----------------
 
// mapAccumL :: (acc -> x -> (acc, y)) -> acc ->
// [x] -> (acc, [y])
const mapAccumL = f =>
// A tuple of an accumulation and a list
// obtained by a combined map and fold,
// with accumulation from left to right.
acc => xs => [...xs].reduce(
(a, x) => {
const tpl = f(a[0])(x);
 
return [
tpl[0],
a[1].concat(tpl[1])
];
},
[acc, []]
);
 
 
// remQuot :: Int -> Int -> (Int, Int)
const remQuot = m =>
n => [m % n, Math.trunc(m / n)];
 
 
// second :: (a -> b) -> ((c, a) -> (c, b))
const second = f =>
// A function over a simple value lifted
// to a function over a tuple.
// f (a, b) -> (a, f(b))
xy => [xy[0], f(xy[1])];
 
 
// zip :: [a] -> [b] -> [(a, b)]
const zip = xs =>
// The paired members of xs and ys, up to
// the length of the shorter of the two lists.
ys => Array.from({
length: Math.min(xs.length, ys.length)
}, (_, i) => [xs[i], ys[i]]);
 
 
// MAIN --
return main();
})();</syntaxhighlight>
{{Out}}
<pre>MDCLXVI
MCMXC
MMVIII
MMXVI
MMXVIII
MMXX</pre>
 
====Declarative====
<syntaxhighlight lang="javascript">function toRoman(num) {
return 'I'
.repeat(num)
.replace(/IIIII/g, 'V')
.replace(/VV/g, 'X')
.replace(/XXXXX/g, 'L')
.replace(/LL/g, 'C')
.replace(/CCCCC/g, 'D')
.replace(/DD/g, 'M')
.replace(/VIIII/g, 'IX')
.replace(/LXXXX/g, 'XC')
.replace(/XXXX/g, 'XL')
.replace(/DCCCC/g, 'CM')
.replace(/CCCC/g, 'CD')
.replace(/IIII/g, 'IV');
}
 
console.log(toRoman(1666));</syntaxhighlight>
{{Out}}
<syntaxhighlight lang="javascript">MDCLXVI</syntaxhighlight>
 
=={{header|jq}}==
 
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
 
The "easy-to-code" version is presented first, followed
by the "orders of magnitude" version. Both versions
work for positive integers up to and including 399,999,
but note that the Unicode glyphs for 50,000 and 100,000 are not supported in many environments.
 
The test cases and output
are identical for both versions and are therefore not repeated.
 
===Easy-to-code version===
<syntaxhighlight lang="jq">def to_roman_numeral:
def romans:
[100000, "\u2188"],
[90000, "ↂ\u2188"],
[50000, "\u2187"],
[40000, "ↂ\u2187"],
[10000, "ↂ"],
[9000, "Mↂ"],
[5000, "ↁ"],
[4000, "Mↁ"],
[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"] ;
if . < 1 or . > 399999
then "to_roman_numeral: \(.) is out of range" | error
else reduce romans as [$i, $r] ({n: .};
until (.n < $i;
.res += $r
| .n = .n - $i ) )
| .res
end ;</syntaxhighlight>
'''Test Cases'''
<syntaxhighlight lang="jq">def testcases: [1668, 1990, 2008, 2020, 4444, 5000, 8999, 39999, 89999, 399999];
 
"Decimal => Roman:",
(testcases[]
| " \(.) => \(to_roman_numeral)" )</syntaxhighlight>
{{out}}
<pre>
Decimal => Roman:
1668 => MDCLXVIII
1990 => MCMXC
2008 => MMVIII
2020 => MMXX
4444 => MↁCDXLIV
5000 => ↁ
8999 => ↁMMMCMXCIX
39999 => ↂↂↂMↂCMXCIX
89999 => ↇↂↂↂMↂCMXCIX
399999 => ↈↈↈↂↈMↂCMXCIX
</pre>
 
==="Orders of Magnitude" version===
'''Translated from [[#Julia|Julia]]''' extended to 399,999
<syntaxhighlight lang="jq">def digits: tostring | explode | map( [.]|implode|tonumber);
# Non-negative integer to Roman numeral up to 399,999
def to_roman_numeral:
if . < 1 or . > 399999
then "to_roman_numeral: \(.) is out of range" | error
else [["I", "X", "C", "M", "ↂ", "\u2188"], ["V", "L", "D", "ↁ", "\u2187"]] as $DR
| (digits|reverse) as $digits
| reduce range(0;$digits|length) as $omag ({rnum: ""};
$digits[$omag] as $d
| if $d == 0 then .omr = ""
elif $d < 4 then .omr = $DR[0][$omag] * $d
elif $d == 4 then .omr = $DR[0][$omag] + $DR[1][$omag]
elif $d == 5 then .omr = $DR[1][$omag]
elif $d < 9 then .omr = $DR[1][$omag] + ($DR[0][$omag] * ($d - 5))
else .omr = $DR[0][$omag] + $DR[0][$omag+1]
end
| .rnum = .omr + .rnum )
| .rnum
end;
</syntaxhighlight>
 
=={{header|Jsish}}==
This covers both Encode (toRoman) and Decode (fromRoman).
 
<syntaxhighlight lang="javascript">/* Roman numerals, in Jsish */
var Roman = {
ord: ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'],
val: [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
 
fromRoman: function(roman:string):number {
var n = 0;
var re = /IV|IX|I|V|XC|XL|X|L|CD|CM|C|D|M/g;
var matches = roman.match(re);
if (!matches) return NaN;
for (var hit of matches) n += this.val[this.ord.indexOf(hit)];
return n;
},
 
toRoman: function(n:number):string {
var roman = '';
var idx = 0;
while (n > 0) {
while (n >= this.val[idx]) {
roman += this.ord[idx];
n -= this.val[idx];
}
idx++;
}
return roman;
}
};
 
provide('Roman', 1);
 
if (Interp.conf('unitTest')) {
; Roman.fromRoman('VIII');
; Roman.fromRoman('MMMDIV');
; Roman.fromRoman('CDIV');
; Roman.fromRoman('MDCLXVI');
; Roman.fromRoman('not');
 
; Roman.toRoman(8);
; Roman.toRoman(3504);
; Roman.toRoman(404);
; Roman.toRoman(1666);
}
 
/*
=!EXPECTSTART!=
Roman.fromRoman('VIII') ==> 8
Roman.fromRoman('MMMDIV') ==> 3504
Roman.fromRoman('CDIV') ==> 404
Roman.fromRoman('MDCLXVI') ==> 1666
Roman.fromRoman('not') ==> NaN
Roman.toRoman(8) ==> VIII
Roman.toRoman(3504) ==> MMMDIV
Roman.toRoman(404) ==> CDIV
Roman.toRoman(1666) ==> MDCLXVI
=!EXPECTEND!=
*/</syntaxhighlight>
 
{{out}}
<pre>prompt$ jsish -u Roman.jsi
[PASS] Roman.jsi</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">using Printf
 
function romanencode(n::Integer)
if n < 1 || n > 4999 throw(DomainError()) end
 
DR = [["I", "X", "C", "M"] ["V", "L", "D", "MMM"]]
rnum = ""
for (omag, d) in enumerate(digits(n))
if d == 0
omr = ""
elseif d < 4
omr = DR[omag, 1] ^ d
elseif d == 4
omr = DR[omag, 1] * DR[omag, 2]
elseif d == 5
omr = DR[omag, 2]
elseif d < 9
omr = DR[omag, 2] * DR[omag, 1] ^ (d - 5)
else
omr = DR[omag, 1] * DR[omag + 1, 1]
end
rnum = omr * rnum
end
return rnum
end
 
testcases = [1990, 2008, 1668]
function toRoman$( value)
append!(testcases, rand(1:4999, 12))
i =0
testcases = unique(testcases)
result$ =""
 
for i = 0 to 12
println("Test romanencode, arabic => roman:")
while value >=arabic( i)
for n in testcases
result$ = result$ + roman$( i)
value @printf("%-4i => value%s\n", n, - arabicromanencode( in))
end</syntaxhighlight>
wend
 
next i
{{out}}
toRoman$ =result$
<pre>Test romanencode, arabic => roman:
end function
1990 => MCMXC
</lang>
2008 => MMVIII
1668 => MDCLXVIII
2928 => MMCMXXVIII
129 => CXXIX
4217 => MMMMCCXVII
1503 => MDIII
2125 => MMCXXV
1489 => MCDLXXXIX
3677 => MMMDCLXXVII
1465 => MCDLXV
1421 => MCDXXI
1642 => MDCXLII
572 => DLXXII
3714 => MMMDCCXIV</pre>
 
=={{header|Kotlin}}==
<syntaxhighlight lang="scala">val romanNumerals = mapOf(
1000 to "M",
900 to "CM",
500 to "D",
400 to "CD",
100 to "C",
90 to "XC",
50 to "L",
40 to "XL",
10 to "X",
9 to "IX",
5 to "V",
4 to "IV",
1 to "I"
)
 
fun encode(number: Int): String? {
if (number > 5000 || number < 1) {
return null
}
var num = number
var result = ""
for ((multiple, numeral) in romanNumerals.entries) {
while (num >= multiple) {
num -= multiple
result += numeral
}
}
return result
}
 
fun main(args: Array<String>) {
println(encode(1990))
println(encode(1666))
println(encode(2008))
}</syntaxhighlight>
 
{{out}}
<pre>
MCMXC
2009 MMIX
1666 MDCLXVI
MMVIII
3888 MMMDCCCLXXXVIII
</pre>
Alternatively:
<syntaxhighlight lang="scala">fun Int.toRomanNumeral(): String {
fun digit(k: Int, unit: String, five: String, ten: String): String {
return when (k) {
in 1..3 -> unit.repeat(k)
4 -> unit + five
in 5..8 -> five + unit.repeat(k - 5)
9 -> unit + ten
else -> throw IllegalArgumentException("$k not in range 1..9")
}
}
return when (this) {
0 -> ""
in 1..9 -> digit(this, "I", "V", "X")
in 10..99 -> digit(this / 10, "X", "L", "C") + (this % 10).toRomanNumeral()
in 100..999 -> digit(this / 100, "C", "D", "M") + (this % 100).toRomanNumeral()
in 1000..3999 -> "M" + (this - 1000).toRomanNumeral()
else -> throw IllegalArgumentException("${this} not in range 0..3999")
}
}</syntaxhighlight>
 
=={{header|Lasso}}==
<syntaxhighlight lang="lasso">define br => '\r'
// encode roman
define encodeRoman(num::integer)::string => {
local(ref = array('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))
local(out = string)
with i in #ref do => {
while(#num >= #i->second) => {
#out->append(#i->first)
#num -= #i->second
}
}
return #out
}
 
'1990 in roman is '+encodeRoman(1990)
br
'2008 in roman is '+encodeRoman(2008)
br
'1666 in roman is '+encodeRoman(1666)</syntaxhighlight>
 
=={{header|LaTeX}}==
The macro <code>\Roman</code> is defined for uppercase roman numeral, accepting as ''argument'' a name of an existing counter.
 
<syntaxhighlight lang="latex">\documentclass{minimal}
\newcounter{currentyear}
\setcounter{currentyear}{\year}
\begin{document}
Anno Domini \Roman{currentyear}
\end{document}</syntaxhighlight>
 
=={{header|LiveCode}}==
<syntaxhighlight lang="livecode">function toRoman intNum
local roman,numArabic
put "M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I" into romans
put "1000,900,500,400,100,90,50,40,10,9,5,4,1" into arabics
put intNum into numArabic
repeat with n = 1 to the number of items of romans
put numArabic div item n of arabics into nums
if nums > 0 then
put repeatChar(item n of romans,nums) after roman
add -(nums * item n of arabics) to numArabic
end if
end repeat
return roman
end toRoman
 
function repeatChar c n
local cc
repeat n times
put c after cc
end repeat
return cc
end repeatChar</syntaxhighlight>
 
Examples
<pre>toRoman(2009) -- MMIX
toRoman(1666) -- MDCLXVI
toRoman(1984) -- MCMLXXXIV
toRoman(3888) -- MMMDCCCLXXXVIII</pre>
 
=={{header|Logo}}==
<langsyntaxhighlight lang="logo">make "roman.rules [
[1000 M] [900 CM] [500 D] [400 CD]
[ 100 C] [ 90 XC] [ 50 L] [ 40 XL]
Line 1,799 ⟶ 4,813:
if :n < first first :rules [output (roman :n bf :rules :acc)]
output (roman :n - first first :rules :rules word :acc last first :rules)
end</langsyntaxhighlight>
 
{{works with|UCB Logo}}
<langsyntaxhighlight lang="logo">make "patterns [[?] [? ?] [? ? ?] [? ?2] [?2] [?2 ?] [?2 ? ?] [?2 ? ? ?] [? ?3]]
 
to digit :d :numerals
Line 1,819 ⟶ 4,833:
print roman 1999 ; MCMXCIX
print roman 25 ; XXV
print roman 944 ; CMXLIV</langsyntaxhighlight>
 
=={{header|LOLCODE}}==
<syntaxhighlight lang="lolcode">HAI 1.2
I HAS A Romunz ITZ A BUKKIT
Romunz HAS A SRS 0 ITZ "M"
Romunz HAS A SRS 1 ITZ "CM"
Romunz HAS A SRS 2 ITZ "D"
Romunz HAS A SRS 3 ITZ "CD"
Romunz HAS A SRS 4 ITZ "C"
Romunz HAS A SRS 5 ITZ "XC"
Romunz HAS A SRS 6 ITZ "L"
Romunz HAS A SRS 7 ITZ "XL"
Romunz HAS A SRS 8 ITZ "X"
Romunz HAS A SRS 9 ITZ "IX"
Romunz HAS A SRS 10 ITZ "V"
Romunz HAS A SRS 11 ITZ "IV"
Romunz HAS A SRS 12 ITZ "I"
 
I HAS A Valuez ITZ A BUKKIT
Valuez HAS A SRS 0 ITZ 1000
Valuez HAS A SRS 1 ITZ 900
Valuez HAS A SRS 2 ITZ 500
Valuez HAS A SRS 3 ITZ 400
Valuez HAS A SRS 4 ITZ 100
Valuez HAS A SRS 5 ITZ 90
Valuez HAS A SRS 6 ITZ 50
Valuez HAS A SRS 7 ITZ 40
Valuez HAS A SRS 8 ITZ 10
Valuez HAS A SRS 9 ITZ 9
Valuez HAS A SRS 10 ITZ 5
Valuez HAS A SRS 11 ITZ 4
Valuez HAS A SRS 12 ITZ 1
 
HOW IZ I Romunize YR Num
I HAS A Result ITZ ""
IM IN YR Outer UPPIN YR Dummy TIL BOTH SAEM Num AN 0
IM IN YR Inner UPPIN YR Index TIL BOTH SAEM Index AN 13
BOTH SAEM Num AN BIGGR OF Num AN Valuez'Z SRS Index, O RLY?
YA RLY
Num R DIFF OF Num AN Valuez'Z SRS Index
Result R SMOOSH Result Romunz'Z SRS Index MKAY
GTFO
OIC
IM OUTTA YR Inner
IM OUTTA YR Outer
FOUND YR Result
IF U SAY SO
 
VISIBLE SMOOSH 2009 " = " I IZ Romunize YR 2009 MKAY MKAY
VISIBLE SMOOSH 1666 " = " I IZ Romunize YR 1666 MKAY MKAY
VISIBLE SMOOSH 3888 " = " I IZ Romunize YR 3888 MKAY MKAY
KTHXBYE</syntaxhighlight>
 
{{Out}}
<pre>2009 = MMIX
1666 = MDCLXVI
3888 = MMMDCCCLXXXVIII</pre>
 
=={{header|LotusScript}}==
<langsyntaxhighlight lang="lss">
Function toRoman(value) As String
Dim arabic(12) As Integer
Line 1,867 ⟶ 4,938:
End Function
 
</syntaxhighlight>
</lang>
 
=={{header|Lua}}==
 
<langsyntaxhighlight lang="lua">romans = {
{1000, "M"},
{900, "CM"}, {500, "D"}, {400, "CD"}, {100, "C"},
Line 1,884 ⟶ 4,956:
end
end
print()</langsyntaxhighlight>
 
=={{header|M4}}==
<langsyntaxhighlight M4lang="m4">define(`roman',`ifelse(eval($1>=1000),1,`M`'roman(eval($1-1000))',
`ifelse(eval($1>=900),1,`CM`'roman(eval($1-900))',
`ifelse(eval($1>=500),1,`D`'roman(eval($1-500))',
Line 1,901 ⟶ 4,973:
)')')')')')')')')')')')')dnl
dnl
roman(3675)</langsyntaxhighlight>
 
{{out}}
Output:
<pre>
MMMDCLXXV
</pre>
 
=={{header|MathematicaMaple}}==
<syntaxhighlight lang="maple">> for n in [ 1666, 1990, 2008 ] do printf( "%d\t%s\n", n, convert( n, 'roman' ) ) end:
Define a custom function that works on positive numbers (RomanForm[0] will not be evaluated):
1666 MDCLXVI
<lang Mathematica>RomanForm[i_Integer?Positive] :=
1990 MCMXC
Module[{num = i, string = "", value, letters, digits},
2008 MMVIII</syntaxhighlight>
digits = {{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"}, {100,
 
"C"}, {90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"}, {9,
=={{header|Mathematica}}/{{header|Wolfram Language}}==
"IX"}, {5, "V"}, {4, "IV"}, {1, "I"}};
RomanNumeral is a built-in function in the Wolfram language. Examples:
While[num > 0, {value, letters} =
<syntaxhighlight lang="mathematica">RomanNumeral[4]
Which @@ Flatten[{num >= #[[1]], ##} & /@ digits, 1];
RomanNumeral[99]
num -= value;
RomanNumeral[1337]
string = string <> letters;];
RomanNumeral[1666]
string]</lang>
RomanNumeral[6889]</syntaxhighlight>
Examples:
<lang Mathematica>RomanForm[4]
RomanForm[99]
RomanForm[1337]
RomanForm[1666]
RomanForm[6889]</lang>
gives back:
<pre>IV
<lang Mathematica>IV
XCIX
MCCCXXXVII
MDCLXVI
MMMMMMDCCCLXXXIX</langpre>
 
== {{header|Mercury}} ==
 
The non-ceremonial work in this program starts at the function <code>to_roman/1</code>. Unusually for Mercury the function is semi-deterministic. This is because some of the helper functions it calls are also semi-deterministic and the determinism subsystem propagates the status upward. (There are ways to stop it from doing this, but it would distract from the actual Roman numeral conversion process so the semi-determinism has been left in.)
Line 1,957 ⟶ 5,024:
=== roman.m ===
 
<syntaxhighlight lang="mercury">
<lang Mercury>
:- module roman.
 
Line 2,010 ⟶ 5,077:
 
:- end_module roman.
</syntaxhighlight>
</lang>
 
=== Usage and output ===
 
{{out}}
<pre>
$ '''mmc roman && ./roman 1 8 27 64 125 216 343 512 729 1000 1331 1728 2197 2744 3375'''
''1 => I''
Line 2,030 ⟶ 5,097:
''2744 => MMDCCXLIV''
''3375 => MMMCCCLXXV''
</pre>
 
=== roman2.m ===
Line 2,035 ⟶ 5,103:
Another implementation using an algorithm inspired by [[#Erlang|the Erlang implementation]] could look like this:
 
<syntaxhighlight lang="mercury">
<lang Mercury>
:- module roman2.
 
Line 2,084 ⟶ 5,152:
 
:- end_module roman2.
</syntaxhighlight>
</lang>
 
This implementation calculates the value of the thousands, then the hundreds, then the tens, then the ones. In each case it uses the <code>digit/4</code> function and some tricks with unification to build the appropriate list of characters for the digit and multiplier being targeted.
 
Its output is identical to that of the previous version.
 
=={{header|Miranda}}==
<syntaxhighlight lang="miranda">main :: [sys_message]
main = [ Stdout (show n ++ ": " ++ toroman n ++ "\n")
| n <- [1990, 2008, 1666, 2023]]
 
toroman :: num->[char]
toroman 0 = ""
toroman n = d ++ toroman (n - v)
where digits = [("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)]
(d, v) = hd [(d,v) | (d,v) <- digits; v <= n]</syntaxhighlight>
{{out}}
<pre>1990: MCMXC
2008: MMVIII
1666: MDCLXVI
2023: MMXXIII</pre>
 
=={{header|Modula-2}}==
{{trans|DWScript}}
{{works with|ADW Modula-2|any (Compile with the linker option ''Console Application'').}}
<syntaxhighlight lang="modula2">
MODULE RomanNumeralsEncode;
 
FROM Strings IMPORT
Append;
FROM STextIO IMPORT
WriteString, WriteLn;
 
CONST
MaxChars = 15;
(* 3888 or MMMDCCCLXXXVIII (15 chars) is the longest string properly encoded
with these symbols. *)
 
TYPE
TRomanNumeral = ARRAY [0 .. MaxChars - 1] OF CHAR;
 
PROCEDURE ToRoman(AValue: CARDINAL; VAR OUT Destination: ARRAY OF CHAR);
TYPE
TRomanSymbols = ARRAY [0 .. 1] OF CHAR;
TWeights = ARRAY [0 .. 12] OF CARDINAL;
TSymbols = ARRAY [0 .. 12] OF TRomanSymbols;
CONST
Weights = TWeights {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
Symbols = TSymbols {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX",
"V", "IV", "I"};
VAR
I: CARDINAL;
BEGIN
Destination := "";
I := 0;
WHILE (I <= HIGH(Weights)) AND (AValue > 0) DO
WHILE AValue >= Weights[I] DO
Append(Symbols[I], Destination);
AValue := AValue - Weights[I]
END;
INC(I);
END;
END ToRoman;
 
VAR
Numeral: TRomanNumeral;
 
BEGIN
ToRoman(1990, Numeral); WriteString(Numeral); WriteLn; (* MCMXC *)
ToRoman(2018, Numeral); WriteString(Numeral); WriteLn; (* MMXVIII *)
ToRoman(3888, Numeral); WriteString(Numeral); WriteLn; (* MMMDCCCLXXXVIII *)
END RomanNumeralsEncode.
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMXVIII
MMMDCCCLXXXVIII
</pre>
 
=={{header|MUMPS}}==
<langsyntaxhighlight MUMPSlang="mumps">TOROMAN(INPUT)
;Converts INPUT into a Roman numeral. INPUT must be an integer between 1 and 3999
;OUTPUT is the string to return
Line 2,104 ⟶ 5,249:
.FOR Q:CURRVAL<$PIECE(ROMANVAL,"^",I) SET OUTPUT=OUTPUT_$PIECE(ROMANNUM,"^",I),CURRVAL=CURRVAL-$PIECE(ROMANVAL,"^",I)
KILL I,CURRVAL
QUIT OUTPUT</langsyntaxhighlight>
{{out}}
Output:<pre>USER>W $$ROMAN^ROSETTA(1666)
<pre>USER>W $$ROMAN^ROSETTA(1666)
MDCLXVI
USER>W $$TOROMAN^ROSETTA(2010)
Line 2,115 ⟶ 5,261:
USER>W $$TOROMAN^ROSETTA(-949)
Invalid input</pre>
 
Another variant
<syntaxhighlight lang="mumps">TOROMAN(n)
;return empty string if input parameter 'n' is not in 1-3999
Quit:(n'?1.4N)!(n'<4000)!'n ""
New r Set r=""
New p Set p=$Length(n)
New j,x
For j=1:1:p Do
. Set x=$Piece("~I~II~III~IV~V~VI~VII~VIII~IX","~",$Extract(n,j)+1)
. Set x=$Translate(x,"IVX",$Piece("IVX~XLC~CDM~M","~",p-j+1))
. Set r=r_x
Quit r</syntaxhighlight>
 
=={{header|Nim}}==
{{trans|Python}}
<syntaxhighlight lang="nim">import strutils
 
const nums = [(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")]
 
proc toRoman(n: Positive): string =
var n = n.int
for (a, r) in nums:
result.add(repeat(r, n div a))
n = n mod a
 
for i in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
25, 30, 40, 50, 60, 69, 70, 80, 90, 99,
100, 200, 300, 400, 500, 600, 666, 700, 800, 900,
1000, 1009, 1444, 1666, 1945, 1997, 1999,
2000, 2008, 2010, 2011, 2500, 3000, 3999]:
echo ($i).align(4), ": ", i.toRoman</syntaxhighlight>
 
{{out}}
<pre> 1: I
2: II
3: III
4: IV
5: V
6: VI
7: VII
8: VIII
9: IX
10: X
11: XI
12: XII
13: XIII
14: XIV
15: XV
16: XVI
17: XVII
18: XVIII
19: XIX
20: XX
25: XXV
30: XXX
40: XL
50: L
60: LX
69: LXIX
70: LXX
80: LXXX
90: XC
99: XCIX
100: C
200: CC
300: CCC
400: CD
500: D
600: DC
666: DCLXVI
700: DCC
800: DCCC
900: CM
1000: M
1009: MIX
1444: MCDXLIV
1666: MDCLXVI
1945: MCMXLV
1997: MCMXCVII
1999: MCMXCIX
2000: MM
2008: MMVIII
2010: MMX
2011: MMXI
2500: MMD
3000: MMM
3999: MMMCMXCIX</pre>
 
=={{header|Objeck}}==
{{trans|C sharp}}
<langsyntaxhighlight lang="objeck">
bundle Default {
class Roman {
Line 2,151 ⟶ 5,387:
}
}
</syntaxhighlight>
</lang>
 
=={{header|OCaml}}==
Line 2,157 ⟶ 5,393:
With an explicit decimal digit representation list:
 
<langsyntaxhighlight lang="ocaml">let digit x y z = function
1 -> [x]
| 2 -> [x;x]
Line 2,179 ⟶ 5,415:
digit 'X' 'L' 'C' (x / 10) @ to_roman (x mod 10)
else
digit 'I' 'V' 'X' x</langsyntaxhighlight>
 
Output:
 
{{out}}
<pre>
# to_roman 1999;;
Line 2,191 ⟶ 5,426:
- : char list = ['C'; 'M'; 'X'; 'L'; 'I'; 'V']
</pre>
 
=={{header|Oforth}}==
 
<syntaxhighlight lang="oforth">[ [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"] ] const: Romans
 
: roman(n)
| r |
StringBuffer new
Romans forEach: r [ while(r first n <=) [ r second << n r first - ->n ] ] ;</syntaxhighlight>
 
=={{header|OpenEdge/Progress}}==
<langsyntaxhighlight lang="progress">FUNCTION encodeRoman RETURNS CHAR (
i_i AS INT
):
Line 2,229 ⟶ 5,473:
1666 encodeRoman( 1666 ) SKIP
VIEW-AS ALERT-BOX.
</syntaxhighlight>
</lang>
{{out}}
Output:
<pre>---------------------------
Message (Press HELP to view stack trace)
Line 2,244 ⟶ 5,488:
=={{header|Oz}}==
{{trans|Haskell}}
<langsyntaxhighlight lang="oz">declare
fun {Digit X Y Z K}
unit([X] [X X] [X X X] [X Y] [Y] [Y X] [Y X X] [Y X X X] [X Z])
Line 2,260 ⟶ 5,504:
end
in
{ForAll {Map [1999 25 944] ToRoman} System.showInfo}</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
Old-style Roman numerals
<langsyntaxhighlight lang="parigp">oldRoman(n)={
while(n>999999,
n-=1000000;
Line 2,318 ⟶ 5,562:
);
print()
};</langsyntaxhighlight>
 
This simple version of medieval Roman numerals does not handle large numbers.
<langsyntaxhighlight lang="parigp">medievalRoman(n)={
while(n>999,
n-=1000;
Line 2,375 ⟶ 5,619:
);
print()
};</langsyntaxhighlight>
 
=={{header|Pascal}}==
See [[Roman_numerals/Encode#Delphi | Delphi]]
 
=={{header|Peloton}}==
Roman numbers are built in to Peloton as a particular form of national number. However, for the sake of the task the _RO opcode has been defined.
<syntaxhighlight lang="sgml"><@ DEFUDOLITLIT>_RO|__Transformer|<@ DEFKEYPAR>__NationalNumericID|2</@><@ LETRESCS%NNMPAR>...|1</@></@>
 
<@ ENU$$DLSTLITLIT>1990,2008,1,2,64,124,1666,10001|,|
<@ SAYELTLST>...</@> is <@ SAY_ROELTLSTLIT>...|RomanLowerUnicode</@> <@ SAY_ROELTLSTLIT>...|RomanUpperUnicode</@> <@ SAY_ROELTLSTLIT>...|RomanASCII</@>
</@></syntaxhighlight>
 
Same code in padded-out, variable-length English dialect
<syntaxhighlight lang="sgml"><# DEFINE USERDEFINEDOPCODE LITERAL LITERAL>_RO|__Transformer|<# DEFINE KEYWORD PARAMETER>__NationalNumericID|2</#><# LET RESULT CAST NATIONALNUMBER PARAMETER>...|1</#></#>
 
<# ENUMERATION LAMBDASPECIFIEDDELMITER LIST LITERAL LITERAL>1990,2008,1,2,64,124,1666,10001|,|
<# SAY ELEMENT LIST>...</#> is <# SAY _RO ELEMENT LIST LITERAL>...|RomanLowerUnicode</#> <# SAY _RO ELEMENT LIST LITERAL>...|RomanUpperUnicode</#> <# SAY _RO ELEMENT LIST LITERAL>...|RomanASCII</#>
</#></syntaxhighlight>
 
{{out}} Notice here the three different ways of representing the results.
For reasons for notational differences, see [[wp:Roman_numerals#Alternate_forms]]
<pre>1990 is ⅿⅽⅿⅹⅽ ⅯⅭⅯⅩⅭ MCMXC
2008 is ⅿⅿⅷ ⅯⅯⅧ MMVIII
1 is ⅰ Ⅰ I
2 is ⅱ Ⅱ II
64 is ⅼⅹⅳ ⅬⅩⅣ LXIV
124 is ⅽⅹⅹⅳ ⅭⅩⅩⅣ CXXIV
1666 is ⅿⅾⅽⅼⅹⅵ ⅯⅮⅭⅬⅩⅥ MDCLXVI
10001 is ⅿⅿⅿⅿⅿⅿⅿⅿⅿⅿⅰ ↂⅠ MMMMMMMMMMI</pre>
 
=={{header|Perl}}==
==== Simple program ====
{{works with|Lingua::Romana::Perligata}}
Simple, fast, produces same output as the Math::Roman module and the Raku example, less crazy than writing a Latin program, and doesn't require experimental modules like the Raku translation.
Perligata outputs numbers in Arabic, but the verb ''come'' ("beautify") may be used to convert numbers to proper Roman numerals:
<syntaxhighlight lang="perl">my @symbols = ( [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'] );
 
sub roman {
my($n, $r) = (shift, '');
($r, $n) = ('-', -$n) if $n < 0; # Optional handling of negative input
foreach my $s (@symbols) {
my($arabic, $roman) = @$s;
($r, $n) = ($r .= $roman x int($n/$arabic), $n % $arabic)
if $n >= $arabic;
}
$r;
}
 
say roman($_) for 1..2012;</syntaxhighlight>
 
==== Using a module ====
<lang perl>per quisque in I tum C conscribementum sic
<syntaxhighlight lang="perl">use Math::Roman qw/roman/;
hoc tum duos multiplicamentum comementum egresso scribe.
say roman($_) for 1..2012'</syntaxhighlight>
cis</lang>
 
==== Ported version of Perl6Raku ====
<syntaxhighlight lang="perl">use List::MoreUtils qw( natatime );
<lang perl>use v5.12;
use Sub::SmartMatch;
use SmartMatch::Sugar qw(any);
use List::MoreUtils qw( natatime );
 
my %symbols = (
Line 2,403 ⟶ 5,684:
);
 
multisub roman => [0], sub { '' };
return '' if 0 == (my $n = shift);
multi roman => any, sub {
my $n = shift;
my $iter = natatime 2, @subtractors;
while( my ($cut, $minus) = $iter->() ) {
Line 2,413 ⟶ 5,693:
and return $symbols{$minus} . roman($n + $minus);
}
};</lang>
 
print roman($_) . "\n" for 1..2012;</syntaxhighlight>
==== Sample usage ====
<lang perl>say roman($_) for 1..2_012;</lang>
 
=={{header|Perl 6Phix}}==
<!--(phixonline)-->
<syntaxhighlight lang="phix">
with javascript_semantics
function toRoman(integer v)
sequence roman = {"M", "CM", "D","CD", "C","XC","L","XL","X","IX","V","IV","I"},
decml = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 }
string res = ""
integer val = v
for i=1 to length(roman) do
while val>=decml[i] do
res &= roman[i]
val -= decml[i]
end while
end for
return {v,res} -- (for output)
end function
 
?apply({1990,2008,1666},toRoman)
<lang perl6>my %symbols =
</syntaxhighlight>
1 => "I", 5 => "V", 10 => "X", 50 => "L", 100 => "C",
{{out}}
500 => "D", 1_000 => "M";
<pre>
{{1990,"MCMXC"},{2008,"MMVIII"},{1666,"MDCLXVI"}}
</pre>
=== cheating slightly ===
<syntaxhighlight lang="phix">
with javascript_semantics
requires("1.0.5")
function toRoman(integer n)
return {n,sprintf("%R",n)}
end function
</syntaxhighlight>
same output (builtins\VM\pprntfN.e/toRoman() is somewhat more obfuscated and faster than the above)
 
=={{header|Phixmonti}}==
my @subtractors =
<syntaxhighlight lang="phixmonti">include ..\Utilitys.pmt
1_000, 100, 500, 100, 100, 10, 50, 10, 10, 1, 5, 1, 1, 0;
 
def romanEnc /# n -- s #/
multi sub roman (0) { '' }
var number
multi sub roman (Int $n) {
"" var res
for @subtractors -> $cut, $minus {
( ( 1000 "M" ) ( 900 "CM" ) ( 500 "D" ) ( 400 "CD" ) ( 100 "C" ) ( 90 "XC" )
$n >= $cut
( 50 "L" ) ( 40 "XL" ) ( 10 "X" ) ( 9 "IX" ) ( 5 "V" ) ( 4 "IV" ) ( 1 "I" ) )
and return %symbols{$cut} ~ roman($n - $cut);
$n >= $cut - $minus
len for
and return %symbols{$minus} ~ roman($n + $minus);
} get 1 get
number over / int
}</lang>
number rot mod var number
swap 2 get rot dup if
for drop res over chain var res endfor
else
drop
endif
drop drop
endfor
drop
res
enddef
 
1968 romanEnc print</syntaxhighlight>
==== Sample usage ====
{{trans|Lua}}
<syntaxhighlight lang="phixmonti">def romanEnc /# n -- s #/
var k
( ( 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" ) )
 
len for
<lang perl6>for 1 .. 2_010 -> $x {
get 2 get var let 1 get var val drop
say roman($x);
k val >=
}</lang>
while
k val - var k
let print
k val >=
endwhile
endfor
drop nl
enddef
 
1968 romanEnc</syntaxhighlight>
Without vars
<syntaxhighlight lang="phixmonti">def romanEnc /# n -- s #/
>ps
( ( 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" ) )
 
len for
get 2 get swap 1 get nip
tps over >=
while
ps> over - >ps
over print
tps over >=
endwhile
drop drop
endfor
ps> drop drop nl
enddef
 
1968 romanEnc</syntaxhighlight>
 
=={{header|PHP}}==
{{works with|PHP|4+ tested in 5.2.12}}
<langsyntaxhighlight lang="php">
/**
* int2roman
Line 2,506 ⟶ 5,859:
return $numeral . $leastSig;
}
</syntaxhighlight>
</lang>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">go =>
List = [455,999,1990,1999,2000,2001,2008,2009,2010,2011,2012,1666,3456,3888,4000],
foreach(Val in List)
printf("%4d: %w\n", Val, roman_encode(Val))
end,
nl.
 
roman_encode(Val) = Res =>
if Val <= 0 then
Res := -1
else
Arabic = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
Roman = ["M", "CM", "D", "CD", "C", "XC","L","XL","X","IX","V","IV","I"],
Res = "",
foreach(I in 1..Arabic.length)
while(Val >= Arabic[I])
Res := Res ++ Roman[I],
Val := Val - Arabic[I]
end
end
end.</syntaxhighlight>
 
{{out}}
<pre> 455: CDLV
999: CMXCIX
1990: MCMXC
1999: MCMXCIX
2000: MM
2001: MMI
2008: MMVIII
2009: MMIX
2010: MMX
2011: MMXI
2012: MMXII
1666: MDCLXVI
3456: MMMCDLVI
3888: MMMDCCCLXXXVIII
4000: MMMM</pre>
 
===Longest numeral===
Which number encodes to the longest Roman numerals in the interval 1..4000:
<syntaxhighlight lang="picat">go2 =>
All = [Len=I=roman_encode(I) : I in 1..4000,E=roman_encode(I), Len=E.len].sort_down,
println(All[1..2]),
nl.</syntaxhighlight>
{{out}}
<pre>[15 = 3888 = MMMDCCCLXXXVIII,14 = 3887 = MMMDCCCLXXXVII]</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de roman (N)
(pack
(make
Line 2,518 ⟶ 5,921:
(link C) ) )
'(M CM D CD C XC L XL X IX V IV I)
(1000 900 500 400 100 90 50 40 10 9 5 4 1) ) ) ) )</langsyntaxhighlight>
{{out}}
Output:
<pre>: (roman 1009)
-> "MIX"
Line 2,527 ⟶ 5,930:
 
=={{header|Pike}}==
<langsyntaxhighlight lang="pike">import String;
int main(){
write(int2roman(2009) + "\n");
write(int2roman(1666) + "\n");
write(int2roman(1337) + "\n");
}</langsyntaxhighlight>
 
=={{header|plainTeX}}==
TeX has its own way to convert a number into roman numeral, but it produces lowercase letters; the following macro (and usage example), produce uppercase roman numeral.
 
<lang tex>\def\upperroman#1{\uppercase\expandafter{\romannumeral#1}}
Anno Domini \upperroman{\year}
\bye</lang>
 
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
/* From Wiki Fortran */
roman: procedure (n) returns(character (32) varying);
Line 2,562 ⟶ 5,958:
return (r);
end roman;
</syntaxhighlight>
</lang>
Results:
<pre>
Line 2,573 ⟶ 5,969:
 
=={{header|PL/SQL}}==
<syntaxhighlight lang="pl/sql">
<lang PL/SQL>
 
/*****************************************************************
Line 2,582 ⟶ 5,978:
*/
 
CREATE OR REPLACE
DECLARE
FUNCTION rencode(an IN NUMBER) RETURN VARCHAR2 IS
rsRETURN VARCHAR2(20);
IS
BEGIN
SELECT RETURN to_char(to_char(to_date(an,'YYYY'), 'RRRR'), 'RN') INTO rs FROM dual;
END rencode;
RETURN rs;
END;
 
BEGIN
Line 2,599 ⟶ 5,995:
 
END;
</syntaxhighlight>
</lang>
 
=={{header|PowerBASICplainTeX}}==
TeX has its own way to convert a number into roman numeral, but it produces lowercase letters; the following macro (and usage example), produce uppercase roman numeral.
{{trans|BASIC}}
 
<syntaxhighlight lang="tex">\def\upperroman#1{\uppercase\expandafter{\romannumeral#1}}
{{works with|PB/Win|8+}}
Anno Domini \upperroman{\year}
\bye</syntaxhighlight>
 
=={{header|PowerShell}}==
{{works with|PB/CC|5}}
<syntaxhighlight lang="powershell">
Filter ToRoman {
$output = ''
if ($_ -ge 4000) {
throw 'Number too high'
}
$current = 1000
$subtractor = 'M'
$whole = $False
$decimal = $_
'C','D','X','L','I','V',' ' `
| %{
$divisor = $current
if ($whole = !$whole) {
$current /= 10
$subtractor = $_ + $subtractor[0]
$_ = $subtractor[1]
}
else {
$divisor *= 5
$subtractor = $subtractor[0] + $_
}
$multiple = [Math]::floor($decimal / $divisor)
if ($multiple) {
$output += [string]$_ * $multiple
$decimal %= $divisor
}
if ($decimal -ge ($divisor -= $current)) {
$output += $subtractor
$decimal -= $divisor
}
}
$output
}
</syntaxhighlight>
<syntaxhighlight lang="powershell">
19,4,0,2479,3001 | ToRoman
</syntaxhighlight>
{{Out}}
<pre>
XIX
IV
 
MMCDLXXIX
<lang powerbasic>FUNCTION toRoman(value AS INTEGER) AS STRING
MMMI DIM arabic(0 TO 12) AS INTEGER
</pre>
DIM roman(0 TO 12) AS STRING
ARRAY ASSIGN arabic() = 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
ARRAY ASSIGN roman() = "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
 
DIM i AS INTEGER
DIM result AS STRING
 
FOR i = 0 TO 12
DO WHILE value >= arabic(i)
result = result & roman(i)
value = value - arabic(i)
LOOP
NEXT i
toRoman = result
END FUNCTION
 
FUNCTION PBMAIN
'Testing
? "2009 = " & toRoman(2009)
? "1666 = " & toRoman(1666)
? "3888 = " & toRoman(3888)
END FUNCTION</lang>
 
=={{header|Prolog}}==
Works{{works with |SWI-Prolog and library clpfd.<BR>}}
{{libheader|clpfd}}
Library clpfd assures that the program works in both managements : Roman towards Arabic and Arabic towards Roman.
<langsyntaxhighlight Prologlang="prolog">:- use_module(library(clpfd)).
 
roman :-
Line 2,738 ⟶ 6,162:
my_print(A, R) :-
format('~w in roman is ~w~n', [A, R]).
</syntaxhighlight>
</lang>
{{out}}
Output :
<pre> ?- roman.
1789 in roman is MDCCLXXXIX
Line 2,749 ⟶ 6,173:
</pre>
 
=={{header|ProtiumPython}}==
===Pythonic===
Roman numbers are built in to Protium as a particular form of national number. However, for the sake of the task the _RO opcode has been defined.
<syntaxhighlight lang="python">import roman
<lang html><@ DEFUDOLITLIT>_RO|__Transformer|<@ DEFKEYPAR>__NationalNumericID|2</@><@ LETRESCS%NNMPAR>...|1</@></@>
print(roman.toRoman(2022))</syntaxhighlight>
 
===Minimalistic structuralism===
<@ ENU$$DLSTLITLIT>1990,2008,1,2,64,124,1666,10001|,|
<syntaxhighlight lang="python">def toRoman(n):
<@ SAYELTLST>...</@> is <@ SAY_ROELTLSTLIT>...|RomanLowerUnicode</@> <@ SAY_ROELTLSTLIT>...|RomanUpperUnicode</@> <@ SAY_ROELTLSTLIT>...|RomanASCII</@>
res='' #converts int to str(Roman numeral)
</@></lang>
reg=n #using the numerals (M,D,C,L,X,V,I)
if reg<4000:#no more than three repetitions
while reg>=1000: #thousands up to MMM
res+='M' #MAX is MMMCMXCIX
reg-=1000
if reg>=900: #nine hundreds in 900-999
res+='CM'
reg-=900
if reg>=500: #five hudreds in 500-899
res+='D'
reg-=500
if reg>=400: #four hundreds in 400-499
res+='CD'
reg-=400
while reg>=100: #hundreds in 100-399
res+='C'
reg-=100
if reg>=90: #nine tens in 90-99
res+='XC'
reg-=90
if reg>=50: #five Tens in 50-89
res+='L'
reg-=50
if reg>=40:
res+='XL' #four Tens
reg-=40
while reg>=10:
res+="X" #tens
reg-=10
if reg>=9:
res+='IX' #nine Units
reg-=9
if reg>=5:
res+='V' #five Units
reg-=5
if reg>=4:
res+='IV' #four Units
reg-=4
while reg>0: #three or less Units
res+='I'
reg-=1
return res</syntaxhighlight>
 
===Imperative===
Same code in padded-out, variable-length English dialect
# Version for Python 2
<lang html><# DEFINE USERDEFINEDOPCODE LITERAL LITERAL>_RO|__Transformer|<# DEFINE KEYWORD PARAMETER>__NationalNumericID|2</#><# LET RESULT CAST NATIONALNUMBER PARAMETER>...|1</#></#>
<syntaxhighlight lang="python">roman = "MDCLXVmdclxvi"; # UPPERCASE for thousands #
 
<# ENUMERATION LAMBDASPECIFIEDDELMITER LIST LITERAL LITERAL>1990,2008,1,2,64,124,1666,10001|,|
<# SAY ELEMENT LIST>...</#> is <# SAY _RO ELEMENT LIST LITERAL>...|RomanLowerUnicode</#> <# SAY _RO ELEMENT LIST LITERAL>...|RomanUpperUnicode</#> <# SAY _RO ELEMENT LIST LITERAL>...|RomanASCII</#>
</#></lang>
 
Output. Notice here the three different ways of representing the results. For reasons for notational differences, see [[wp:Roman_numerals#Alternate_forms]]
<pre>1990 is ⅿⅽⅿⅹⅽ ⅯⅭⅯⅩⅭ MCMXC
2008 is ⅿⅿⅷ ⅯⅯⅧ MMVIII
1 is ⅰ Ⅰ I
2 is ⅱ Ⅱ II
64 is ⅼⅹⅳ ⅬⅩⅣ LXIV
124 is ⅽⅹⅹⅳ ⅭⅩⅩⅣ CXXIV
1666 is ⅿⅾⅽⅼⅹⅵ ⅯⅮⅭⅬⅩⅥ MDCLXVI
10001 is ⅿⅿⅿⅿⅿⅿⅿⅿⅿⅿⅰ ↂⅠ MMMMMMMMMMI</pre>
 
=={{header|PureBasic}}==
<lang PureBasic>#SymbolCount = 12 ;0 based count
DataSection
denominations:
Data.s "M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I" ;0-12
denomValues:
Data.i 1000,900,500,400,100,90,50,40,10,9,5,4,1 ;values in decending sequential order
EndDataSection
 
;-setup
Structure romanNumeral
symbol.s
value.i
EndStructure
Global Dim refRomanNum.romanNumeral(#SymbolCount)
 
Restore denominations
For i = 0 To #SymbolCount
Read.s refRomanNum(i)\symbol
Next
 
Restore denomValues
For i = 0 To #SymbolCount
Read refRomanNum(i)\value
Next
 
Procedure.s decRoman(n)
;converts a decimal number to a roman numeral
Protected roman$, i
For i = 0 To #SymbolCount
Repeat
If n >= refRomanNum(i)\value
roman$ + refRomanNum(i)\symbol
n - refRomanNum(i)\value
Else
Break
EndIf
ForEver
Next
 
ProcedureReturn roman$
EndProcedure
 
If OpenConsole()
 
PrintN(decRoman(1999)) ;MCMXCIX
PrintN(decRoman(1666)) ;MDCLXVI
PrintN(decRoman(25)) ;XXV
PrintN(decRoman(954)) ;CMLIV
 
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf</lang>
 
=={{header|Python}}==
<lang python>roman = "MDCLXVmdclxvi"; # UPPERCASE for thousands #
adjust_roman = "CCXXmmccxxii";
arabic = (1000000, 500000, 100000, 50000, 10000, 5000, 1000, 500, 100, 50, 10, 5, 1);
Line 2,856 ⟶ 6,249:
2000,2008,2500,3000,4000,4999,5000,6666,10000,50000,100000,500000,1000000);
for val in test:
print '%d - %s'%(val, arabic_to_roman(val))</langsyntaxhighlight>
An alternative which uses the divmod() function<langsyntaxhighlight lang="python">romanDgts= 'ivxlcdmVXLCDM_'
 
def ToRoman(num):
Line 2,872 ⟶ 6,265:
else:
namoR += r*romanDgts[rdix] + (romanDgts[rdix+1] if(v==1) else '')
return namoR[-1::-1]</langsyntaxhighlight>
 
It is more Pythonic to use zip to iterate over two lists together:
<langsyntaxhighlight lang="python">anums = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
rnums = "M CM D CD C XC L XL X IX V IV I".split()
 
Line 2,893 ⟶ 6,286:
for val in test:
print '%d - %s'%(val, to_roman(val))
</syntaxhighlight>
</lang>
 
# Version for Python 3
<syntaxhighlight lang="python">def arabic_to_roman(dclxvi):
#===========================
'''Convert an integer from the decimal notation to the Roman notation'''
org = dclxvi; # 666 #
out = "";
for scale, arabic_scale in enumerate(arabic):
if org == 0: break
multiples = org // arabic_scale;
org -= arabic_scale * multiples;
out += roman[scale] * multiples;
if (org >= -adjust_arabic[scale] + arabic_scale):
org -= -adjust_arabic[scale] + arabic_scale;
out += adjust_roman[scale] + roman[scale]
return out
 
if __name__ == "__main__":
test = (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,30,40,50,60,69,70,
80,90,99,100,200,300,400,500,600,666,700,800,900,1000,1009,1444,1666,1945,1997,1999,
2000,2008,2500,3000,4000,4999,5000,6666,10000,50000,100000,500000,1000000);
for val in test:
print("%8d %s" %(val, arabic_to_roman(val)))</syntaxhighlight>
 
===Declarative===
Less readable, but a 'one liner':
<syntaxhighlight lang="python">rnl = [ { '4' : 'MMMM', '3' : 'MMM', '2' : 'MM', '1' : 'M', '0' : '' }, { '9' : 'CM', '8' : 'DCCC', '7' : 'DCC',
'6' : 'DC', '5' : 'D', '4' : 'CD', '3' : 'CCC', '2' : 'CC', '1' : 'C', '0' : '' }, { '9' : 'XC',
'8' : 'LXXX', '7' : 'LXX', '6' : 'LX', '5' : 'L', '4' : 'XL', '3' : 'XXX', '2' : 'XX', '1' : 'X',
'0' : '' }, { '9' : 'IX', '8' : 'VIII', '7' : 'VII', '6' : 'VI', '5' : 'V', '4' : 'IV', '3' : 'III',
'2' : 'II', '1' : 'I', '0' : '' }]
# Option 1
def number2romannumeral(n):
return ''.join([rnl[x][y] for x, y in zip(range(4), str(n).zfill(4)) if n < 5000 and n > -1])
# Option 2
def number2romannumeral(n):
return reduce(lambda x, y: x + y, map(lambda x, y: rnl[x][y], range(4), str(n).zfill(4))) if -1 < n < 5000 else None</syntaxhighlight>
 
 
Or, defining '''roman''' in terms of '''mapAccumL''':
{{works with|Python|3}}
{{Trans|Haskell}}
<syntaxhighlight lang="python">'''Encoding Roman Numerals'''
 
from functools import reduce
from itertools import chain
 
 
# romanFromInt :: Int -> String
def romanFromInt(n):
'''A string of Roman numerals encoding an integer.'''
def go(a, ms):
m, s = ms
q, r = divmod(a, m)
return (r, s * q)
 
return concat(snd(mapAccumL(go)(n)(
zip([
1000, 900, 500, 400, 100, 90, 50,
40, 10, 9, 5, 4, 1
], [
'M', 'CM', 'D', 'CD', 'C', 'XC', 'L',
'XL', 'X', 'IX', 'V', 'IV', 'I'
])
)))
 
 
# ------------------------- TEST -------------------------
# main :: IO ()
def main():
'''Sample of years'''
for s in [
romanFromInt(x) for x in [
1666, 1990, 2008, 2016, 2018, 2020
]
]:
print(s)
 
 
# ------------------ GENERIC FUNCTIONS -------------------
 
# concat :: [[a]] -> [a]
# concat :: [String] -> String
def concat(xxs):
'''The concatenation of all the elements in a list.'''
xs = list(chain.from_iterable(xxs))
unit = '' if isinstance(xs, str) else []
return unit if not xs else (
''.join(xs) if isinstance(xs[0], str) else xs
)
 
 
# mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
def mapAccumL(f):
'''A tuple of an accumulation and a list derived by a
combined map and fold,
with accumulation from left to right.'''
def go(a, x):
tpl = f(a[0], x)
return (tpl[0], a[1] + [tpl[1]])
return lambda acc: lambda xs: (
reduce(go, xs, (acc, []))
)
 
 
# snd :: (a, b) -> b
def snd(tpl):
'''Second component of a tuple.'''
return tpl[1]
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>MDCLXVI
MCMXC
MMVIII
MMXVI
MMXVIII
MMXX</pre>
 
=={{header|Quackery}}==
 
Pasting epitomised.
 
<syntaxhighlight lang="quackery"> [ $ ""
swap 1000 /mod $ "M" rot of rot swap join swap
dup 900 < not if [ 900 - dip [ $ "CM" join ] ]
dup 500 < not if [ 500 - dip [ $ "D" join ] ]
dup 400 < not if [ 400 - dip [ $ "CD" join ] ]
100 /mod $ "C" rot of rot swap join swap
dup 90 < not if [ 90 - dip [ $ "XC" join ] ]
dup 50 < not if [ 50 - dip [ $ "L" join ] ]
dup 40 < not if [ 40 - dip [ $ "XL" join ] ]
10 /mod $ "X" rot of rot swap join swap
dup 9 < not if [ 9 - dip [ $ "IX" join ] ]
dup 5 < not if [ 5 - dip [ $ "V" join ] ]
dup 4 < not if [ 4 - dip [ $ "IV" join ] ]
$ "I" swap of join ]
is ->roman ( n --> $ )
 
1990 dup echo say " = " ->roman echo$ cr
2008 dup echo say " = " ->roman echo$ cr
1666 dup echo say " = " ->roman echo$ cr</syntaxhighlight>
 
{{Out}}
 
<pre>1990 = MCMXC
2008 = MMVIII
1666 = MDCLXVI</pre>
 
=={{header|R}}==
R has a built-in function, <code>[https://svn.r-project.org/R/trunk/src/library/utils/R/roman.R as.roman]</code>, for conversion to Roman numerals. The implementation details are found in <code>utils:::.numeric2roman</code> (see previous link), and <code>utils:::.roman2numeric</code>, for conversion back to Arabic decimals.
<langsyntaxhighlight Rlang="r">as.roman(1666) # MDCLXVI</langsyntaxhighlight>
Since the object <code>as.roman</code> creates is just an integer vector with a class, you can do arithmetic with Roman numerals:
<langsyntaxhighlight Rlang="r">as.roman(1666) + 334 # MM</langsyntaxhighlight>
 
=={{header|Racket}}==
Straight recursion:
<langsyntaxhighlight Racketlang="racket">#lang racket
(define (encode/roman number)
(cond ((>= number 1000) (string-append "M" (encode/roman (- number 1000))))
Line 2,914 ⟶ 6,459:
((>= number 40) (string-append "XL" (encode/roman (- number 40))))
((>= number 10) (string-append "X" (encode/roman (- number 10))))
((>= number 9) (string-append "IX" (encode/roman (- number 9))))
((>= number 5) (string-append "V" (encode/roman (- number 5))))
((>= number 4) (string-append "IV" (encode/roman (- number 4))))
((>= number 1) (string-append "I" (encode/roman (- number 1))))
(else "")))</langsyntaxhighlight>
 
Using for/fold and quotient/remainder to remove repetition:
<langsyntaxhighlight Racketlang="racket">#lang racket
(define (number->list n)
(for/fold ([result null])
([decimal '(1000 900 500 400 100 90 50 40 10 9 5 4 1)]
[roman '(M CM D CD C XC L XL X IX V IV I)])
#:break (= n 0)
(let-values ([(q r) (quotient/remainder n decimal)])
Line 2,937 ⟶ 6,483:
1000 1009 1444 1666 1945 1997 1999 2000 2008 2010 2011 2500
3000 3999)])
(printf "~a ~a\n" n (encode/roman n)))</langsyntaxhighlight>
 
=={{header|Raku}}==
(formerly Perl 6)
 
<syntaxhighlight lang="raku" line>my %symbols =
1 => "I", 5 => "V", 10 => "X", 50 => "L", 100 => "C",
500 => "D", 1_000 => "M";
 
my @subtractors =
1_000, 100, 500, 100, 100, 10, 50, 10, 10, 1, 5, 1, 1, 0;
 
multi sub roman (0) { '' }
multi sub roman (Int $n) {
for @subtractors -> $cut, $minus {
$n >= $cut
and return %symbols{$cut} ~ roman($n - $cut);
$n >= $cut - $minus
and return %symbols{$minus} ~ roman($n + $minus);
}
}
 
# Sample usage
 
for 1 .. 2_010 -> $x {
say roman($x);
}</syntaxhighlight>
 
=={{header|Red}}==
Straight iterative solution:
<syntaxhighlight lang="red">
Red []
 
table: [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]
 
to-Roman: function [n [integer!] return: [string!]][
out: copy ""
foreach [a r] table [while [n >= a][append out r n: n - a]]
out
]
 
foreach number [40 33 1888 2016][print [number ":" to-Roman number]]
</syntaxhighlight>
Straight recursive solution:
<syntaxhighlight lang="red">
Red []
 
table: [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]
 
to-Roman: func [n [integer!] return: [string!]][
case [
tail? table [table: head table copy ""]
table/1 > n [table: skip table 2 to-Roman n]
'else [append copy form table/2 to-Roman n - table/1]
]
]
 
foreach number [40 33 1888 2016][print [number ":" to-Roman number]]
</syntaxhighlight>
This solution builds, using metaprogramming, a `case` table, that relies on recursion to convert every digit.
 
<syntaxhighlight lang="red">
Red []
 
to-Roman: function [n [integer!]] reduce [
'case collect [
foreach [a r] [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][
keep compose/deep [n >= (a) [append copy (form r) any [to-Roman n - (a) copy ""]]]
]
]
]
 
foreach number [40 33 1888 2016][print [number ":" to-Roman number]]
</syntaxhighlight>
 
=={{header|Retro}}==
This is a port of the [[Forth]] code; but returns a string rather than displaying the roman numerals. It only handles numbers between 1 and 3999.
 
<syntaxhighlight lang="retro">
<lang Retro>
: vector ( ...n"- )
here [ &, times ] dip : .data ` swap ` + ` @ ` do ` ; ;
Line 2,967 ⟶ 6,586:
dup 1 3999 within 0 =
[ "EX LIMITO!\n" ] [ "IVXLCDM" swap record here ] if ;
</syntaxhighlight>
</lang>
 
=={{header|REXX}}==
===version 1===
<langsyntaxhighlight lang="rexx">roman: procedure
arg number
 
Line 2,987 ⟶ 6,606:
end
end
return result</langsyntaxhighlight>
===version 2===
This version of a REXX program allows almost any non-negative (whole) decimal numberinteger.
<br><br>Most people think that the Romans had no word for "zero". &nbsp; The Roman numeral system has no need for a
<br>zero ''placeholder'', so there was no name for it (just as we have no name for a "¶" in the middle of our numbers ---
<br>as we don't have that possibility). &nbsp; However, the Romans did have a name for zero (or nothing).
<br>In fact the Romans had several names for zero (see the REXX code), as does modern English. &nbsp; In American English, many words can be used:
<br>zero, nothing, naught, bupkis, zilch, goose-egg, nebbish, squat, nil, crapola, what-Patty-shot-at, nineteen (only in cribbage), love (in tennis), etc.
<br><br>Also, this REXX version supports large numbers (with parentheses and deep parentheses).
<br>(This code was ripped out of my general routine that also supported versions for Attic, ancient Roman, and modern Roman numerals.)
<br>The code is bulkier than most at it deals with any non-negative decimal number, and more boilerplate code is(was) present to handle the above versions.
<lang rexx>/*REXX program converts (Arabic) decimal numbers (≥0) ──► Roman numerals*/
numeric digits 10000 /*could be higher if wanted*/
parse arg nums
 
Most people think that the Romans had no word for "zero". &nbsp; The Roman numeral system has no need for a
if nums='' then do /*not specified? Gen some.*/
<br>zero &nbsp; ''placeholder'', &nbsp; so there was no name for it &nbsp; (just as we have no name for a &nbsp; "¶" &nbsp; in the middle of our
do j=0 by 11 to 111
<br>numbers ─── as we don't have that possibility). &nbsp; However, the Romans did have a name for zero (or nothing).
nums=nums j
<br>In fact the Romans had several names for zero &nbsp; (see the REXX code), &nbsp; as does modern English. &nbsp; In American
end /*j*/
<br>English, many words can be used for &nbsp; '''0''': &nbsp; &nbsp; zero, nothing, naught, bupkis, zilch, goose-egg, nebbish, squat, nil,
nums=nums 49
<br>crapola, what-Patty-shot-at, nineteen (only in cribbage), love (in tennis), etc.
do k=88 by 100 to 1200
nums=nums k
end /*k*/
nums=nums 1000 2000 3000 4000 5000 6000
do m=88 by 200 to 1200
nums=nums m
end /*m*/
nums=nums 1304 1405 1506 1607 1708 1809 1910 2011
do p=4 to 50 /*there is no limit to this*/
nums=nums 10**p
end /*p*/
end /*end generation of numbers*/
 
Also, this REXX version supports large numbers (with parentheses and deep parentheses).
do i=1 for words(nums); x=word(nums,i)
say right(x,55) dec2rom(x)
end /*i*/
exit /*stick a fork in it, we're done.*/
/*───────────────────────────DEC2ROM subroutine─────────────────────────*/
dec2rom: procedure; parse arg n,# /*get number, assign # to a null. */
n=space(translate(n,,','),0) /*remove any commas from number. */
nulla='ZEPHIRUM NULLAE NULLA NIHIL' /*Roman words for nothing or none.*/
if n==0 then return word(nulla,1) /*return a Roman word for zero. */
maxnp=(length(n)-1)%3 /*find max(+1) # of parens to use.*/
highPos=(maxnp+1)*3 /*highest position of number. */
nn=reverse(right(n,highPos,0)) /*digits for Arabic───►Roman conv.*/
nine=9
four=4; do j=highPos to 1 by -3
_=substr(nn,j,1); select
when _==nine then hx='CM'
when _>= 5 then hx='D'copies("C",_-5)
when _==four then hx='CD'
otherwise hx=copies('C',_)
end
_=substr(nn,j-1,1); select
when _==nine then tx='XC'
when _>= 5 then tx='L'copies("X",_-5)
when _==four then tx='XL'
otherwise tx=copies('X',_)
end
_=substr(nn,j-2,1); select
when _==nine then ux='IX'
when _>= 5 then ux='V'copies("I",_-5)
when _==four then ux='IV'
otherwise ux=copies('I',_)
end
xx=hx || tx || ux
if xx\=='' then #=# ||copies('(',(j-1)%3)xx ||copies(')',(j-1)%3)
end /*j*/
 
(This REXX code was ripped out of my general routine that also supported versions for '''Attic''', '''ancient Roman''',
if pos('(I',#)\==0 then do i=1 for 4 /*special case: M,MM,MMM,MMMM.*/
<br>and '''modern Roman''' numerals.)
if i==4 then _ = '(IV)'
 
else _ = '('copies("I",i)')'
The general REXX code is bulkier than most at it deals with &nbsp; ''any'' &nbsp; non-negative decimal number, &nbsp; and more
if pos(_,#)\==0 then #=changestr(_,#,copies('M',i))
<br>boilerplate code is in the general REXX code to handle the above versions.
end /*i*/
<syntaxhighlight lang="rexx">/*REXX program converts (Arabic) non─negative decimal integers (≥0) ───► Roman numerals.*/
return #</lang>
numeric digits 10000 /*decimal digs can be higher if wanted.*/
Some older REXXes don't have a &nbsp; '''changestr''' &nbsp; BIF, so one is included here ──► [[CHANGESTR.REX]].
parse arg # /*obtain optional integers from the CL.*/
<br><br>
@er= "argument isn't a non-negative integer: " /*literal used when issuing error msg. */
'''output''' when using the default input (within the REXX program):
if #='' then /*Nothing specified? Then generate #s.*/
<pre style="height:40ex;overflow:scroll">
do
do j= 0 by 11 to 111; #=# j; end
#=# 49; do k=88 by 100 to 1200; #=# k; end
#=# 1000 2000 3000 4000 5000 6000; do m=88 by 200 to 1200; #=# m; end
#=# 1304 1405 1506 1607 1708 1809 1910 2011; do p= 4 to 50; #=# 10**p; end
end /*finished with generation of numbers. */
 
do i=1 for words(#); x=word(#, i) /*convert each of the numbers───►Roman.*/
if \datatype(x, 'W') | x<0 then say "***error***" @er x /*¬ whole #? negative?*/
say right(x, 55) dec2rom(x)
end /*i*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
dec2rom: procedure; parse arg n,# /*obtain the number, assign # to a null*/
n=space(translate(n/1, , ','), 0) /*remove commas from normalized integer*/
nulla= 'ZEPHIRUM NULLAE NULLA NIHIL' /*Roman words for "nothing" or "none". */
if n==0 then return word(nulla, 1) /*return a Roman word for "zero". */
maxnp=(length(n)-1)%3 /*find max(+1) # of parenthesis to use.*/
highPos=(maxnp+1)*3 /*highest position of number. */
nn=reverse( right(n, highPos, 0) ) /*digits for Arabic──►Roman conversion.*/
do j=highPos to 1 by -3
_=substr(nn, j, 1); select /*════════════════════hundreds.*/
when _==9 then hx='CM'
when _>=5 then hx='D'copies("C", _-5)
when _==4 then hx='CD'
otherwise hx= copies('C', _)
end /*select hundreds*/
_=substr(nn, j-1, 1); select /*════════════════════════tens.*/
when _==9 then tx='XC'
when _>=5 then tx='L'copies("X", _-5)
when _==4 then tx='XL'
otherwise tx= copies('X', _)
end /*select tens*/
_=substr(nn, j-2, 1); select /*═══════════════════════units.*/
when _==9 then ux='IX'
when _>=5 then ux='V'copies("I", _-5)
when _==4 then ux='IV'
otherwise ux= copies('I', _)
end /*select units*/
$=hx || tx || ux
if $\=='' then #=# || copies("(", (j-1)%3)$ ||copies(')', (j-1)%3)
end /*j*/
if pos('(I',#)\==0 then do i=1 for 4 /*special case: M,MM,MMM,MMMM.*/
if i==4 then _ = '(IV)'
else _ = '('copies("I", i)')'
if pos(_, #)\==0 then #=changestr(_, #, copies('M', i))
end /*i*/
return #</syntaxhighlight>
Some older REXXes don't have a &nbsp; '''changestr''' &nbsp; BIF, &nbsp; so one is included here &nbsp; ──► &nbsp; [[CHANGESTR.REX]]. <br><br>
'''output''' &nbsp; when using the default (internal) input):
<pre style="height:80ex">
0 ZEPHIRUM
11 XI
Line 3,158 ⟶ 6,772:
100000000000000000000000000000000000000000000000000 ((((((((((((((((C))))))))))))))))
</pre>
 
=={{header|Ring}}==
<syntaxhighlight lang="ring">
arabic = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
roman = ["M", "CM", "D", "CD", "C" ,"XC", "L", "XL" ,"X", "IX", "V", "IV", "I"]
 
see "2009 = " + toRoman(2009) + nl
see "1666 = " + toRoman(1666) + nl
see "3888 = " + toRoman(3888) + nl
func toRoman val
result = ""
for i = 1 to 13
while val >= arabic[i]
result = result + roman[i]
val = val - arabic[i]
end
next
return result
</syntaxhighlight>
 
=={{header|RPL}}==
{{trans|Python}}
{{works with|Halcyon Calc|4.2.7}}
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ { 1000 900 500 400 100 90 50 40 10 9 5 4 1 }
{ "M" "CM" "D" "CD" "C" "XC" "L" "XL" "X" "IX"
"V" "IV" "I" } → divs rdig
'''IF''' DUP 5000 < '''THEN'''
"" SWAP 1 13 '''FOR''' j
divs j GET MOD LAST / IP ROT SWAP
'''WHILE''' DUP '''REPEAT'''
rdig j GET ROT SWAP + SWAP 1 - '''END'''
DROP SWAP
'''NEXT'''
'''END''' DROP
≫ ''''→ROM'''' STO
|
'''→ROM''' ''( n -- "ROMAN" )''
store tables
if n < 5000 then
scan divisors
x,y = divmod(n, divisor)
if x > 0 then
add related digit x times
n = y
clean stack
|}
===Alternate version===
{| class="wikitable"
! RPL code
! Comment
|-
|
≪ '''IF''' DUP 5000 < '''THEN'''
{ "IIIVIIIX" "XXXLXXXC" "CCCDCCCM" }
{ 11 21 31 43 44 54 64 74 87 88 } → rom args
≪ "" SWAP
1 3 '''FOR''' j
10 MOD LAST / IP
'''IF''' SWAP '''THEN'''
args LAST GET 10 MOD LAST / IP
rom j GET ROT ROT SUB ROT + SWAP '''END'''
'''NEXT''' ≫
'''WHILE''' DUP '''REPEAT''' 1 - "M" ROT + SWAP '''END'''
DROP '''END'''
≫ ''''→ROM'''' STO
|
'''→ROM''' ''( n -- "M..CXVI" ) ''
collapsed Roman digits
10 arguments to extract Roman digits
initialize stack
process units to hundreds
divmod(n,10)
if last digit ≠ 0 then
get extraction arguments
extract Roman digit
add thousands if any
clean stack
|}
 
=={{header|Ruby}}==
Roman numeral generation was used as an example for demonstrating [http://www.xpsd.org/cgi-bin/wiki?TestDrivenDevelopmentTutorialRomanNumerals Test Driven Development] in Ruby. The solution came to be:
<langsyntaxhighlight lang="ruby">Symbols = { 1=>'I', 5=>'V', 10=>'X', 50=>'L', 100=>'C', 500=>'D', 1000=>'M' }
Subtractors = [ [1000, 100], [500, 100], [100, 10], [50, 10], [10, 1], [5, 1], [1, 0] ]
 
Line 3,174 ⟶ 6,877:
[1990, 2008, 1666].each do |i|
puts "%4d => %s" % [i, roman(i)]
end</langsyntaxhighlight>
 
{{out}}
Line 3,183 ⟶ 6,886:
</pre>
 
Another shorter version if we don't consider calculating the substractors:
=={{header|Run BASIC}}==
<lang runbasic>[loop]
input "Input value:";val$
print roman$(val$)
goto [loop]
 
<syntaxhighlight lang="ruby">
' ------------------------------
Symbols = [ [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'] ]
' Roman numerals
 
' ------------------------------
def arabic_to_roman(arabic)
FUNCTION roman$(val$)
return '' if arabic.zero?
a2r$ = "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"
Symbols.each { |arabic_rep, roman_rep| return roman_rep + arabic_to_roman(arabic - arabic_rep) if arabic >= arabic_rep }
v = val(val$)
end
for i = 1 to 13
</syntaxhighlight>
r$ = word$(a2r$,i,",")
 
a = val(word$(r$,2,":"))
Yet another way to solve it in terms of reduce
while v >= a
 
roman$ = roman$ + word$(r$,1,":")
<syntaxhighlight lang="ruby">
v = v - a
Symbols = [ [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'] ]
wend
 
next i
def to_roman(num)
END FUNCTION</lang>
Symbols.reduce "" do |memo, (divisor, letter)|
div, num = num.divmod(divisor)
memo + letter * div
end
end
</syntaxhighlight>
 
=={{header|Rust}}==
<syntaxhighlight lang="rust">struct RomanNumeral {
symbol: &'static str,
value: u32
}
 
const NUMERALS: [RomanNumeral; 13] = [
RomanNumeral {symbol: "M", value: 1000},
RomanNumeral {symbol: "CM", value: 900},
RomanNumeral {symbol: "D", value: 500},
RomanNumeral {symbol: "CD", value: 400},
RomanNumeral {symbol: "C", value: 100},
RomanNumeral {symbol: "XC", value: 90},
RomanNumeral {symbol: "L", value: 50},
RomanNumeral {symbol: "XL", value: 40},
RomanNumeral {symbol: "X", value: 10},
RomanNumeral {symbol: "IX", value: 9},
RomanNumeral {symbol: "V", value: 5},
RomanNumeral {symbol: "IV", value: 4},
RomanNumeral {symbol: "I", value: 1}
];
 
fn to_roman(mut number: u32) -> String {
let mut min_numeral = String::new();
for numeral in NUMERALS.iter() {
while numeral.value <= number {
min_numeral = min_numeral + numeral.symbol;
number -= numeral.value;
}
}
min_numeral
}
 
fn main() {
let nums = [2014, 1999, 25, 1666, 3888];
for &n in nums.iter() {
// 4 is minimum printing width, for alignment
println!("{:2$} = {}", n, to_roman(n), 4);
}
}</syntaxhighlight>{{out}}
<pre>
2014 = MMXIV
1999 = MCMXCIX
25 = XXV
1666 = MDCLXVI
3888 = MMMDCCCLXXXVIII
</pre>
 
=={{header|Scala}}==
{{works with|Scala|2.8}}
<langsyntaxhighlight lang="scala">val romanDigits = Map(
1 -> "I", 5 -> "V",
10 -> "X", 50 -> "L",
Line 3,219 ⟶ 6,972:
case Some(key) => romanDigits(key) + toRoman(n - key)
case None => ""
}</langsyntaxhighlight>
{{Out}}
 
<pre>scala> List(1990, 2008, 1666) map toRoman
Sample:
res55: List[String] = List(MCMXC, MMVIII, MDCLXVI)</pre>
 
===Using foldLeft===
<pre>
<syntaxhighlight lang="scala">def toRoman( v:Int ) : String = {
scala> List(1990, 2008, 1666) map toRoman
res55: List[String] = List(MCMXC, MMVIII, MDCLXVI)
</pre>
 
==Scala Using foldLeft==
<lang Scala>def toRoman( v:Int ) : String = {
val romanNumerals = List(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")
Line 3,242 ⟶ 6,990:
test(1990)
test(2008)
test(1666)</langsyntaxhighlight>
===Different code-style===
 
<syntaxhighlight lang="scala">def toRoman(num: Int): String = {
Same implementation, different code-style:
 
<lang Scala>def toRoman(num: Int): String = {
case class RomanUnit(value: Int, token: String)
val romanNumerals = List(
Line 3,271 ⟶ 7,017:
}
}
}</langsyntaxhighlight>
 
{{out}}
<pre>1990 => MCMXC
Line 3,281 ⟶ 7,026:
This uses format directives supported in Chez Scheme since v6.9b; YMMV.
 
<langsyntaxhighlight lang="scheme">(define (to-roman n)
(format "~@r" n))</langsyntaxhighlight>
 
This is a general example using Chicken Scheme.
<syntaxhighlight lang="scheme">(define roman-decimal
'(("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)))
 
(define (to-roman value)
(apply string-append
(let loop ((v value)
(decode roman-decimal))
(let ((r (caar decode))
(d (cdar decode)))
(cond
((= v 0) '())
((>= v d) (cons r (loop (- v d) decode)))
(else (loop v (cdr decode))))))))
 
 
(let loop ((n '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 25 30 40
50 60 69 70 80 90 99 100 200 300 400 500 600 666 700 800 900
1000 1009 1444 1666 1945 1997 1999 2000 2008 2010 2011 2500
3000 3999)))
(unless (null? n)
(printf "~a ~a\n" (car n) (to-roman (car n)))
(loop (cdr n))))
</syntaxhighlight>
 
=={{header|Seed7}}==
Line 3,290 ⟶ 7,072:
which writes a roman numeral to a string.
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "stdio.s7i";
include "wrinum.s7i";
Line 3,301 ⟶ 7,083:
writeln(str(ROMAN, number));
end for;
end func;</langsyntaxhighlight>
 
Original source [http://seed7.sourceforge.net/algorith/puzzles.htm#roman_numerals].
 
=={{header|SenseTalk}}==
 
<syntaxhighlight lang="sensetalk">function RomanNumeralsEncode number
put [
(1, "I"),
(4, "IV"),
(5, "V"),
(9, "IX"),
(10, "X"),
(40, "XL"),
(50, "L"),
(90, "XC"),
(100, "C"),
(400, "CD"),
(500, "D"),
(900, "CM"),
(1000, "M")
] into values
repeat for index = each item of (the number of items in values)..1
put item index of values into pair
repeat while number is greater than or equal to the first item of pair
put the second item of pair after numerals
subtract the first item of pair from number
end repeat
end repeat
return numerals
end RomanNumeralsEncode</syntaxhighlight>
 
<syntaxhighlight lang="sensetalk">repeat for each item in [
1990,
2008,
1666
]
put RomanNumeralsEncode(it)
end repeat</syntaxhighlight>
 
{{out}}
<pre>
MCMXC
MMVIII
MDCLXVI
</pre>
 
=={{header|SETL}}==
<syntaxhighlight lang="ada">examples := [2008, 1666, 1990];
 
for example in examples loop
print( roman_numeral(example) );
end loop;
 
proc roman_numeral( n );
R := [[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']];
roman := '';
for numeral in R loop
while n >= numeral(1) loop
n := n - numeral(1);
roman := roman + numeral(2);
end loop;
end loop;
return roman;
end;</syntaxhighlight>
{{out}}
<pre>MMVIII
MDCLXVI
MCMXC</pre>
 
=={{header|Shen}}==
<syntaxhighlight lang="shen">
(define encodeGlyphs
ACC 0 _ -> ACC
ACC N [Glyph Value | Rest] -> (encodeGlyphs (@s ACC Glyph) (- N Value) [Glyph Value | Rest]) where (>= N Value)
ACC N [Glyph Value | Rest] -> (encodeGlyphs ACC N Rest)
)
 
(define encodeRoman
N -> (encodeGlyphs "" N ["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])
)
</syntaxhighlight>
{{out}}
<pre>
(4-) (encodeRoman 1990)
"MCMXC"
 
(5-) (encodeRoman 2008)
"MMVIII"
 
(6-) (encodeRoman 1666)
"MDCLXVI"
</pre>
 
=={{header|Sidef}}==
{{trans|ActionScript}}
<syntaxhighlight lang="ruby">func arabic2roman(num, roman='') {
static 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
];
lookup.each { |pair|
while (num >= pair.second) {
roman += pair.first;
num -= pair.second;
}
}
return roman;
}
say("1990 in roman is " + arabic2roman(1990));
say("2008 in roman is " + arabic2roman(2008));
say("1666 in roman is " + arabic2roman(1666));</syntaxhighlight>
{{out}}
<pre>1990 in roman is MCMXC
2008 in roman is MMVIII
1666 in roman is MDCLXVI</pre>
 
=={{header|Simula}}==
<syntaxhighlight lang="simula">BEGIN
 
TEXT PROCEDURE TOROMAN(N); INTEGER N;
BEGIN
PROCEDURE P(WEIGHT,LIT); INTEGER WEIGHT; TEXT LIT;
BEGIN
WHILE N >= WEIGHT DO
BEGIN
T :- T & LIT;
N := N - WEIGHT;
END WHILE;
END P;
TEXT T; T :- NOTEXT;
P( 1000, "M" );
P( 900, "CM" );
P( 500, "D" );
P( 400, "CD" );
P( 100, "C" );
P( 90, "XC" );
P( 50, "L" );
P( 40, "XL" );
P( 10, "X" );
P( 9, "IX" );
P( 5, "V" );
P( 4, "IV" );
P( 1, "I" );
TOROMAN :- T;
END TOROMAN;
 
INTEGER Y;
FOR Y := 1990, 2008, 1666 DO
BEGIN
OUTTEXT("YEAR ");
OUTINT(Y, 4);
OUTTEXT(" => ");
OUTTEXT(TOROMAN(Y));
OUTIMAGE;
END FOR;
 
END PROGRAM;
</syntaxhighlight>
{{out}}
<pre>
YEAR 1990 => MCMXC
YEAR 2008 => MMVIII
YEAR 1666 => MDCLXVI
</pre>
 
=={{header|Smalltalk}}==
 
{{works with|Smalltalk/X}}
in ST/X, integers already know how to print themselfthemselves as roman number:
<syntaxhighlight lang ="smalltalk">2013 printRomanOn:Stdout naive:false</langsyntaxhighlight>
{{out}}
outputs:<pre>
<pre>
MMXIII</pre>
the implementation is:
<langsyntaxhighlight lang="smalltalk">
printRomanOn:aStream naive:naive
"print the receiver as roman number to the argument, aStream.
Line 3,367 ⟶ 7,317:
] doWhile:[ repeatFlag and:[ restValue >= rValue] ].
].
</syntaxhighlight>
</lang>
 
=={{header|Tcl}}==
<lang tcl>proc to_roman {i} {
set map {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}
foreach {value roman} $map {
while {$i >= $value} {
append res $roman
incr i -$value
}
}
return $res
}</lang>
 
=={{header|SQL}}==
<lang SQL>
--
-- This only works under Oracle and has the limitation of 1 to 3999
--- Higher numbers in the Middle Ages were represented by "superscores" on top of the numeral to multiply by 1000
--- Vertical bars to the sides multiply by 100. So |M| means 100,000
-- When the query is run, user provides the Arabic numerals for the ar_year
-- A.Kebedjiev
--
 
SELECT to_char(to_char(to_date(&ar_year,'YYYY'), 'RRRR'), 'RN') AS roman_year FROM DUAL;
 
-- or you can type in the year directly
 
SELECT to_char(to_char(to_date(1666,'YYYY'), 'RRRR'), 'RN') AS roman_year FROM DUAL;
 
ROMAN_YEAR
MDCLXVI
 
</lang>
 
=={{header|SNOBOL4}}==
Adapted from [http://burks.bton.ac.uk/burks/language/snobol/catspaw/tutorial/ch6.htm Catspaw SNOBOL Tutorial, Chapter 6]
 
<langsyntaxhighlight lang="snobol4">
* ROMAN(N) - Convert integer N to Roman numeral form.
*
Line 3,436 ⟶ 7,353:
OUTPUT = " 944 = " ROMAN(944)
 
END</langsyntaxhighlight>
{{out}}
Outputs:
<pre>
1999 = MCMXCIX
Line 3,446 ⟶ 7,363:
Here's a non-recursive version, and a Roman-to-Arabic converter to boot.
 
<langsyntaxhighlight SNOBOL4lang="snobol4">* # Arabic to Roman
define('roman(n)s,ch,val,str') :(roman_end)
roman roman = ge(n,4000) n :s(return)
Line 3,474 ⟶ 7,391:
astr = astr r '=' arabic(r) ' ' :(tloop)
out output = rstr; output = astr
end</langsyntaxhighlight>
 
{{out}}
Output:
<pre>2010=MMX 1999=MCMXCIX 1492=MCDXCII 1066=MLXVI 476=CDLXXVI
MMX=2010 MCMXCIX=1999 MCDXCII=1492 MLXVI=1066 CDLXXVI=476</pre>
 
=={{header|TI-83 BASICSPL}}==
<syntaxhighlight lang="spl">a2r(a)=
<lang ti83b>PROGRAM:DEC2ROM
r = ""
:"="→Str1
n = [["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"],[1000,900,500,400,100,90,50,40,10,9,5,4,1]]
:Lbl ST
> i, 1..13
:ClrHome
> a!<n[i,2]
:Disp "NUMBER TO"
r += n[i,1]
:Disp "CONVERT:"
a -= n[i,2]
:Input A
<
:If fPart(A) or A≠abs(A)
<
:Then
<= r
:Goto PI
.
:End
 
:A→B
t = [1990,2008,1666]
:While B≥1000
> i, 1..#.size(t,1)
:Str1+"M"→Str1
#.output(t[i]," = ",a2r(t[i]))
:B-1000→B
<</syntaxhighlight>
:End
{{out}}
:If B≥900
<pre>
:Then
1990 = MCMXC
:Str1+"CM"→Str1
2008 = MMVIII
:B-900→B
1666 = MDCLXVI
:End
</pre>
:If B≥500
 
:Then
=={{header|SQL}}==
:Str1+"D"→Str1
<syntaxhighlight lang="sql">
:B-500→B
--
:End
-- This only works under Oracle and has the limitation of 1 to 3999
:If B≥400
 
:Then
 
:Str1+"CD"?Str1
SQL> select to_char(1666, 'RN') urcoman, to_char(1666, 'rn') lcroman from dual;
:B-400→B
:End
:While B≥100
:Str1+"C"→Str1
:B-100→B
:End
:If B≥90
:Then
:Str1+"XC"→Str1
:B-90→B
:End
:If B≥50
:Then
:Str1+"L"→Str1
:B-50→B
:End
:If B≥40
:Then
:Str1+"XL"→Str1
:B-40→B
:End
:While B≥10
:Str1+"X"→Str1
:B-10→B
:End
:If B≥9
:Then
:Str1+"IX"→Str1
:B-9→B
:End
:If B≥5
:Then
:Str1+"V"→Str1
:B-5→B
:End
:If B≥4
:Then
:Str1+"IV"→Str1
:B-4→B
:End
:While B>0
:Str1+"I"→Str1
:B-1→B
:End
:ClrHome
:Disp A
:Disp Str1
:Stop
:Lbl PI
:ClrHome
:Disp "THE NUMBER MUST"
:Disp "BE A POSITIVE"
:Disp "INTEGER."
:Pause
:Goto ST
</lang>
 
URCOMAN LCROMAN
--------------- ---------------
MDCLXVI mdclxvi
</syntaxhighlight>
 
=={{header|Swift}}==
<syntaxhighlight lang="swift">func ator(var n: Int) -> String {
 
var result = ""
for (value, letter) in
[( 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")]
{
while n >= value {
result += letter
n -= value
}
}
return result
}</syntaxhighlight>
Sample call:
{{works with|Swift|1.x}}
<syntaxhighlight lang="swift">println(ator(1666)) // MDCLXVI</syntaxhighlight>
{{works with|Swift|2.0}}
<syntaxhighlight lang="swift">print(ator(1666)) // MDCLXVI</syntaxhighlight>
{{output}}
<pre>MDCLXVI </pre>
 
=={{header|Tailspin}}==
<syntaxhighlight lang="tailspin">
def digits: [(M:1000"1"), (CM:900"1"), (D:500"1"), (CD:400"1"), (C:100"1"), (XC:90"1"), (L:50"1"), (XL:40"1"), (X:10"1"), (IX:9"1"), (V:5"1"), (IV:4"1"), (I:1"1")];
templates encodeRoman
@: 1;
'$ -> ($)"1" -> #;' !
when <$digits($@)::value..> do
$digits($@)::key !
$ - $digits($@)::value -> #
when <1"1"..> do
@:$@ + 1;
$ -> #
end encodeRoman
 
1990 -> encodeRoman -> !OUT::write
'
' -> !OUT::write
2008 -> encodeRoman -> !OUT::write
'
' -> !OUT::write
1666 -> encodeRoman -> !OUT::write
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMVIII
MDCLXVI
</pre>
 
=={{header|Tcl}}==
<syntaxhighlight lang="tcl">proc to_roman {i} {
set map {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}
foreach {value roman} $map {
while {$i >= $value} {
append res $roman
incr i -$value
}
}
return $res
}</syntaxhighlight>
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
LOOP arab_number="1990'2008'1666"
Line 3,575 ⟶ 7,517:
PRINT "Arabic number ",arab_number, " equals ", roman_number
ENDLOOP
</syntaxhighlight>
</lang>
{{out}}
Output:
<pre>
Arabic number 1990 equals MCMXC
Line 3,582 ⟶ 7,524:
Arabic number 1666 equals MDCLXVI
</pre>
 
== {{header|TypeScript}} ==
{{trans|DWScript}}
Weights and symbols in tuples.
<syntaxhighlight lang="javascript">
// Roman numerals/Encode
 
const weightsSymbols: [number, string][] =
[[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']];
// 3888 or MMMDCCCLXXXVIII (15 chars) is the longest string properly encoded
// with these symbols.
 
function toRoman(n: number): string {
var roman = ""; // Result
for (i = 0; i <= 12 && n > 0; i++) {
var w = weightsSymbols[i][0];
while (n >= w) {
roman += weightsSymbols[i][1];
n -= w;
}
}
return roman;
}
 
console.log(toRoman(1990)); // MCMXC
console.log(toRoman(2022)); // MMXXII
console.log(toRoman(3888)); // MMMDCCCLXXXVIII
</syntaxhighlight>
{{out}}
<pre>
MCMXC
MMXXII
MMMDCCCLXXXVIII
</pre>
 
=={{header|UNIX Shell}}==
{{trans|Tcl}}
{{works with|bash}}
<syntaxhighlight lang="bash">roman() {
local values=( 1000 900 500 400 100 90 50 40 10 9 5 4 1 )
local roman=(
[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
)
local nvmber=""
local num=$1
for value in ${values[@]}; do
while (( num >= value )); do
nvmber+=${roman[value]}
((num -= value))
done
done
echo $nvmber
}
 
for test in 1999 24 944 1666 2008; do
printf "%d = %s\n" $test $(roman $test)
done</syntaxhighlight>
{{out}}
<pre>
1999 = MCMXCIX
24 = XXIV
944 = CMXLIV
1666 = MDCLXVI
2008 = MMVIII</pre>
 
=={{header|Ursala}}==
Line 3,592 ⟶ 7,602:
CCCC are replaced by CD. The substitution operator (%=) is helpful
here.
<langsyntaxhighlight Ursalalang="ursala">#import nat
 
roman =
Line 3,598 ⟶ 7,608:
-+
'IIII'%='IV'+ 'VIIII'%='IX'+ 'XXXX'%='XL'+ 'LXXXX'%='XC'+ 'CCCC'%='CD'+ 'DCCCC'%='CM',
~&plrDlSPSL/'MDCLXVI'+ iota*+ +^|(^|C/~&,\/division)@rlX=>~&iNC <1000,500,100,50,10,5>+-</langsyntaxhighlight>
This test program applies the function to each member of a list of numbers.
<langsyntaxhighlight Ursalalang="ursala">#show+
 
test = roman* <1990,2008,1,2,64,124,1666,10001></langsyntaxhighlight>
{{out}}
output:
<pre>MCMXC
MMVIII
Line 3,612 ⟶ 7,622:
MDCLXVI
MMMMMMMMMMI</pre>
 
=={{header|Vala}}==
{{trans|D}}
<syntaxhighlight lang="vala">string to_roman(int n)
requires (n > 0 && n < 5000)
{
const int[] weights = {1000, 900, 500, 400, 100, 90,
50, 40, 10, 9, 5, 4, 1};
const string[] symbols = {"M","CM","D","CD","C","XC","L",
"XL","X","IX","V","IV","I"};
var roman = "", count = 0;
foreach (var w in weights) {
while (n >= w) {
roman += symbols[count];
n -= w;
}
if (n == 0)
break;
count++;
}
return roman;
}
 
void main() {
print("%s\n", to_roman(455));
print("%s\n", to_roman(3456));
print("%s\n", to_roman(2488));
}</syntaxhighlight>
 
{{out}}
<pre>
CDLV
MMMCDLVI
MMCDLXXXVIII
</pre>
 
=={{header|VBA}}==
<syntaxhighlight lang="vb">Private Function roman(n As Integer) As String
roman = WorksheetFunction.roman(n)
End Function
Public Sub main()
s = [{10, 2016, 800, 2769, 1666, 476, 1453}]
For Each x In s
Debug.Print roman(CInt(x)); " ";
Next x
End Sub</syntaxhighlight>{{out}}
<pre>X MMXVI DCCC MMDCCLXIX MDCLXVI CDLXXVI MCDLIII </pre>
 
=={{header|Vedit macro language}}==
<langsyntaxhighlight lang="vedit">// Main program for testing the function
//
do {
Line 3,645 ⟶ 7,703:
}
Buf_Quit(OK)
Return</langsyntaxhighlight>
 
{{out}}
Output:
<pre> 4 = IV
12 = XII
Line 3,654 ⟶ 7,712:
2011 = MMXI</pre>
 
=={{header|VisualV Basic(Vlang)}}==
<syntaxhighlight lang="Zig">
{{trans|BASIC}}
const numerals = {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"}
 
fn main() {
<lang vb>Function toRoman(value) As String
println(encode(1990))
Dim arabic As Variant
println(encode(2008))
Dim roman As Variant
println(encode(1666))
}
 
fn encode(number int) string {
arabic = Array(1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
mut num := number
roman = Array("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I")
mut result := ""
if number < 1 || number > 5000 {return result}
for digit, roman in numerals {
for num >= digit {
num -= digit
result += roman
}
}
return result
}
</syntaxhighlight>
 
{{out}}
Dim i As Integer, result As String
<pre>
MCMXC
MMVIII
MDCLXVI
</pre>
 
=={{header|Wren}}==
For i = 0 To 12
{{trans|Kotlin}}
Do While value >= arabic(i)
<syntaxhighlight lang="wren">var romans = [
result = result + roman(i)
[1000, "M"],
value = value - arabic(i)
[900, Loop"CM"],
Next[500, i "D"],
[400, "CD"],
[100, "C"],
[90, "XC"],
[50, "L"],
[40, "XL"],
[10, "X"],
[9, "IX"],
[5, "V"],
[4, "IV"],
[1, "I"]
]
 
var encode = Fn.new { |n|
toRoman = result
if (n > 5000 || n < 1) return null
End Function
var res = ""
for (r in romans) {
while (n >= r[0]) {
n = n - r[0]
res = res + r[1]
}
}
return res
}
 
System.print(encode.call(1990))
System.print(encode.call(1666))
System.print(encode.call(2008))
System.print(encode.call(2020))</syntaxhighlight>
 
{{out}}
<pre>
MCMXC
MDCLXVI
MMVIII
MMXX
</pre>
 
=={{header|XLISP}}==
<syntaxhighlight lang="lisp">(defun roman (n)
(define roman-numerals '((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")))
(defun romanize (arabic-numeral numerals roman-numeral)
(if (= arabic-numeral 0)
roman-numeral
(if (>= arabic-numeral (caar numerals))
(romanize (- arabic-numeral (caar numerals)) numerals (string-append roman-numeral (cadar numerals)))
(romanize arabic-numeral (cdr numerals) roman-numeral))))
(romanize n roman-numerals ""))
 
; test the function:
(display (mapcar roman '(10 2016 800 2769 1666 476 1453)))</syntaxhighlight>
{{out}}
<pre>(x mmxvi dccc mmdcclxix mdclxvi cdlxxvi mcdliii)</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">proc Rom(N, A, B, C); \Display 1..9 in Roman numerals
int N, A, B, C, I;
[case N of
9: [ChOut(0, C); ChOut(0, A)]; \XI
8,7,6,5:[ChOut(0, B); for I:= 1 to rem(N/5) do ChOut(0, C)]; \V
4: [ChOut(0, C); ChOut(0, B)] \IV
other for I:= 1 to N do ChOut(0, C); \I
];
 
proc Roman(N); \Display N in Roman numerals
int N, Q;
[Q:= N/1000; N:= rem(0); \0..3999
Rom(Q, ^?, ^?, ^M);
Q:= N/100; N:= rem(0); \0..999
Rom(Q, ^M, ^D, ^C);
Q:= N/10; N:= rem(0); \0..99
Rom(Q, ^C, ^L, ^X);
Rom(N, ^X, ^V, ^I); \0..9
];
 
int Tbl, I;
[Tbl:= [1990, 2008, 1666, 0, 1, 3999, 2020, 1234];
for I:= 0 to 7 do
[IntOut(0, Tbl(I)); Text(0, ". "); Roman(Tbl(I)); CrLf(0)];
]</syntaxhighlight>
 
{{out}}
<pre>
1990. MCMXC
2008. MMVIII
1666. MDCLXVI
0.
1. I
3999. MMMCMXCIX
2020. MMXX
1234. MCCXXXIV
</pre>
 
Sub Main()
MsgBox toRoman(Val(InputBox("Number, please")))
End Sub</lang>
=={{header|XSLT}}==
<langsyntaxhighlight lang="xslt">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/data/number">
Line 3,731 ⟶ 7,894:
</xsl:template>
</xsl:stylesheet>
</syntaxhighlight>
</lang>
 
=={{header|zkl}}==
<syntaxhighlight lang="zkl">var [const] romans = L(
L("M", 1000), L("CM", 900), L("D", 500), L("CD", 400), L("C", 100),
L("XC", 90), L("L", 50), L("XL", 40), L("X", 10), L("IX", 9),
L("V", 5), L("IV", 4), L("I", 1));
fcn toRoman(i){ // convert int to a roman number
reg text = "";
foreach R,N in (romans){ text += R*(i/N); i = i%N; }
return(text);
}</syntaxhighlight>
<pre>
toRoman(1990) //-->"MCMXC"
toRoman(2008) //-->"MMVIII"
toRoman(1666) //-->"MDCLXVI"
</pre>
 
=={{header|Zoea}}==
<syntaxhighlight lang="zoea">
program: decimal_roman
input: 12
output: 'XII'
</syntaxhighlight>
 
=={{header|Zoea Visual}}==
[http://zoea.co.uk/examples/zv-rc/Roman_numerals_encode.png Roman numerals encode]
 
=={{header|Zsh}}==
Based on the python solution.
<langsyntaxhighlight lang="zsh">function printroman () {
local -a conv
local number=$1 div rom num out
Line 3,746 ⟶ 7,935:
done
echo $out
}</langsyntaxhighlight>
 
{{omit from|GUISS}}
7,805

edits