Author Topic: Roman Numeral / Decimal Number converter  (Read 3549 times)

0 Members and 1 Guest are viewing this topic.

Offline Jaze

  • Newbie
  • Posts: 86
    • View Profile
Roman Numeral / Decimal Number converter
« on: September 03, 2021, 10:13:21 pm »
Code: QB64: [Select]
  1. CONST TRUE = 1
  2. CONST FALSE = 0
  3. DIM SHARED romanNumeral$: romanNumeral$ = ""
  4. DIM SHARED decimalNumber: decimalNumber = 0
  5.  
  6. PRINT "Type 1 or 'R' to convert decimal number to Roman Numeral"
  7. PRINT "           or anything else to convert Roman Numeral to decimal number"
  8. c$ = P$(TRUE)
  9. IF c$ = "1" OR UCASE$(c$) = "R" THEN
  10.     CALL ConvertToRoman
  11.     CALL ConvertToDecimal
  12.  
  13. SUB ConvertToDecimal
  14.     decimalNumber = 0
  15.     invalidInput:
  16.     INPUT "Type in the Roman Numeral: ", romanNumeral$
  17.     rn$ = UCASE$(romanNumeral$)
  18.     FOR count = 1 TO LEN(rn$)
  19.         a$ = MID$(rn$, count, 1)
  20.         SELECT CASE a$
  21.             CASE "I", "V", "X", "L", "C", "D", "M"
  22.                 'do nothing
  23.             CASE ELSE
  24.                 GOTO invalidInput
  25.         END SELECT
  26.     NEXT count
  27.     DO
  28.         r$ = LEFT$(rn$, 1)
  29.         SELECT CASE r$
  30.             CASE "M"
  31.                 decimalNumber = decimalNumber + 1000
  32.                 rn$ = MID$(rn$, 2, LEN(rn$))
  33.             CASE "C"
  34.                 IF LEFT$(rn$, 2) = "CM" THEN
  35.                     decimalNumber = decimalNumber + 900
  36.                     rn$ = MID$(rn$, 3, LEN(rn$))
  37.                 ELSEIF LEFT$(rn$, 2) = "CD" THEN
  38.                     decimalNumber = decimalNumber + 400
  39.                     rn$ = MID$(rn$, 3, LEN(rn$))
  40.                 ELSE
  41.                     decimalNumber = decimalNumber + 100
  42.                     rn$ = MID$(rn$, 2, LEN(rn$))
  43.                 END IF
  44.             CASE "D"
  45.                 decimalNumber = decimalNumber + 500
  46.                 rn$ = MID$(rn$, 2, LEN(rn$))
  47.             CASE "X"
  48.                 IF LEFT$(rn$, 2) = "XC" THEN
  49.                     decimalNumber = decimalNumber + 90
  50.                     rn$ = MID$(rn$, 3, LEN(rn$))
  51.                 ELSEIF LEFT$(rn$, 2) = "XL" THEN
  52.                     decimalNumber = decimalNumber + 40
  53.                     rn$ = MID$(rn$, 3, LEN(rn$))
  54.                 ELSE
  55.                     decimalNumber = decimalNumber + 10
  56.                     rn$ = MID$(rn$, 2, LEN(rn$))
  57.                 END IF
  58.             CASE "L"
  59.                 decimalNumber = decimalNumber + 50
  60.                 rn$ = MID$(rn$, 2, LEN(rn$))
  61.             CASE "I"
  62.                 IF LEFT$(rn$, 2) = "IX" THEN
  63.                     decimalNumber = decimalNumber + 9
  64.                     rn$ = MID$(rn$, 3, LEN(rn$))
  65.                 ELSEIF LEFT$(rn$, 2) = "IV" THEN
  66.                     decimalNumber = decimalNumber + 4
  67.                     rn$ = MID$(rn$, 3, LEN(rn$))
  68.                 ELSE
  69.                     decimalNumber = decimalNumber + 1
  70.                     rn$ = MID$(rn$, 2, LEN(rn$))
  71.                 END IF
  72.             CASE "V"
  73.                 decimalNumber = decimalNumber + 5
  74.                 rn$ = MID$(rn$, 2, LEN(rn$))
  75.         END SELECT
  76.     LOOP UNTIL rn$ = ""
  77.     COLOR n15, 0: PRINT "Decimal number: " + S$(decimalNumber)
  78.  
  79. SUB ConvertToRoman
  80.     decimalNumber = 0
  81.     romanNumeral$ = ""
  82.     INPUT "Type in the decimal number: ", decimalNumber
  83.     DO
  84.         IF decimalNumber >= 1000 THEN
  85.             romanNumeral$ = romanNumeral$ + "M"
  86.             decimalNumber = decimalNumber - 1000
  87.         ELSEIF decimalNumber >= 900 THEN
  88.             romanNumeral$ = romanNumeral$ + "CM"
  89.             decimalNumber = decimalNumber - 900
  90.         ELSEIF decimalNumber >= 500 THEN
  91.             romanNumeral$ = romanNumeral$ + "D"
  92.             decimalNumber = decimalNumber - 500
  93.         ELSEIF decimalNumber >= 400 THEN
  94.             romanNumeral$ = romanNumeral$ + "CD"
  95.             decimalNumber = decimalNumber - 400
  96.         ELSEIF decimalNumber >= 100 THEN
  97.             romanNumeral$ = romanNumeral$ + "C"
  98.             decimalNumber = decimalNumber - 100
  99.         ELSEIF decimalNumber >= 90 THEN
  100.             romanNumeral$ = romanNumeral$ + "XC"
  101.             decimalNumber = decimalNubmer - 90
  102.         ELSEIF decimalNumber >= 50 THEN
  103.             romanNumeral$ = romanNumeral$ + "L"
  104.             decimalNumber = decimalNumber - 50
  105.         ELSEIF decimalNumber >= 40 THEN
  106.             romanNumeral$ = romanNumeral$ + "XL"
  107.             decimalNumber = decimalNumber - 40
  108.         ELSEIF decimalNumber >= 10 THEN
  109.             romanNumeral$ = romanNumeral$ + "X"
  110.             decimalNumber = decimalNumber - 10
  111.         ELSEIF decimalNumber >= 9 THEN
  112.             romanNumeral$ = romanNumeral$ + "IX"
  113.             decimalNumber = decimalNumer - 9
  114.         ELSEIF decimalNumber >= 5 THEN
  115.             romanNumeral$ = romanNumeral$ + "V"
  116.             decimalNumber = decimalNumber - 5
  117.         ELSEIF decimalNumber >= 4 THEN
  118.             romanNumeral$ = romanNumeral$ + "IV"
  119.             decimalNumber = decimalNumber - 4
  120.         ELSEIF decimalNumber >= 1 THEN
  121.             romanNumeral$ = romanNumeral$ + "I"
  122.             decimalNumber = decimalNumber - 1
  123.         END IF
  124.     LOOP UNTIL decimalNumber = 0
  125.     COLOR 15, 0: PRINT "The Roman Numeral is " + romanNumeral$
  126.  
  127. 'for debugging
  128. FUNCTION P$ (escape)
  129.     pause$ = INPUT$(1)
  130.     IF escape = TRUE AND pause$ = CHR$(27) THEN END
  131.     P$ = pause$
  132. FUNCTION S$ (number)
  133.     rtn$ = ""
  134.     rtn$ = STR$(number)
  135.     rtn$ = LTRIM$(rtn$)
  136.     S$ = rtn$

I thought this would be a lot more difficult than it was

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Roman Numeral / Decimal Number converter
« Reply #1 on: September 03, 2021, 10:32:10 pm »
You wanted more difficult? Try converting to Judaism next time!

Nice. I gave it IV out of V stars.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Roman Numeral / Decimal Number converter
« Reply #2 on: September 04, 2021, 09:06:09 am »
We played with this about a year ago:
Code: QB64: [Select]
  1. _Title "Roman$ Function Test and Demo" ' b+ 2020-09-01 revise Roman SUB to latest changes at forum
  2. Dim q~&, output$, num As _Unsigned Long, test$
  3. q~& = -1: num = 4294967295 'quick test of big number limit
  4. Print num; "= "; Roman$(Str$(num))
  5. '         4294967295    4294967295   'limit
  6. For num = 4294967200 To 4294967220
  7.     output$ = Roman$(Str$(num))
  8.     test$ = Roman$(output$)
  9.     Locate CsrLin, 1: Print num;
  10.     Locate CsrLin, 20: Print output$;
  11.     Locate CsrLin, 50: Print test$
  12.     If num <> Val(test$) Then Beep: Sleep
  13.     Print " Testing conversion of numbers 0 to"; q~&; " to or from Roman Numerals >"
  14.     Input " Enter a string to test "; test$
  15.     output$ = Roman$(test$)
  16.     Print " The Roman SUB returned: "; output$
  17.     Print
  18. Loop Until test$ = ""
  19.  
  20. Function Roman$ (instrg$) ' for extended Roman Numeral conversions
  21.     Static d(12) As _Unsigned Long, c(12) As String, R$(1 To 3999)
  22.     Dim pd As Integer, pr As Integer, lastpd As Integer, lastpr As Integer
  23.     If d(0) = 0 Then ' load n and c arrays
  24.         For ub = 0 To 12
  25.             Read d(ub), c(ub)
  26.         Next
  27.         For i = 1 To 3999
  28.             ub = 12: x = i: conv = ""
  29.             Do ' *** Ashish uses same method as Euklides but condensed beautifully here ***
  30.                 If x >= d(ub) And x < 4 * d(ub) Then ' x falls between which two decimal amounts?
  31.                     p = Int(x / d(ub)): s = "" 'setup to copy Roman symbol(s) p times
  32.                     For j = 1 To p: s = s + c(ub): Next 'string copy
  33.                     conv = conv + s: x = x - d(ub) * p
  34.                 Else
  35.                     ub = ub - 1 'move index ub down
  36.                 End If
  37.             Loop Until x = 0
  38.             R$(i) = conv
  39.         Next
  40.     End If 'end of setup, one time only
  41.     s = _Trim$(UCase$(instrg$))
  42.     If s = "" Or s = "0" Then Roman$ = "Error: nada": Exit Function 'handle nothing
  43.     For i = 1 To Len(s) ' character checkup
  44.         pd = InStr("0123456789", Mid$(s, i, 1)): pr = InStr(" MDCLXVI", Mid$(s, i, 1))
  45.         If pd = 0 And pr = 0 Then Roman$ = "Error: unknown character.": Exit Function 'handle wrong alpha
  46.         If i > 1 Then 'check for mixed messages
  47.             If (lastpd = 0 And pd > 0) Or (lastpr = 0 And pr > 0) Then Roman$ = "Error: digits mixed with letters.": Exit Function
  48.         End If
  49.         lastpd = pd: lastpr = pr
  50.     Next
  51.     v = Val(s) 'is s a number or a Roman Numeral string?
  52.     If v = 0 Then
  53.         ReDim vs(0) As String ' vs for value strings
  54.         Split s, " M", vs() '   Handy Split for parsing *M sections
  55.         conv = "" '             Build our string on this variable (reusing)
  56.         For j = 0 To UBound(vs)
  57.             pd = 0 'reuse an integer for found match
  58.             For i = 1 To 3999
  59.                 If R$(i) = vs(j) Then ' When stringing together numbers after first set need 0 fillers.
  60.                     If j > 0 Then conv = conv + Right$("000" + _Trim$(Str$(i)), 3) Else conv = conv + _Trim$(Str$(i))
  61.                     pd = 1: Exit For 'pd indeicates a match was found
  62.                 End If
  63.             Next
  64.             If pd <> 1 Then ' No match found, maybe this is empty 000 space?
  65.                 If vs(j) = "" Then conv = conv + "000" Else Roman$ = "Error: Invalid Roman Numeral? string.": Exit Function
  66.             End If
  67.         Next
  68.         Roman$ = conv
  69.     ElseIf v >= 4000 Then ' Beyond our Roman String Table
  70.         k = Int(v / 1000)
  71.         Roman$ = Roman$(Str$(k)) + " " + Roman$(Str$(v - (k - 1) * 1000)) ' Go recursive until v < 4000
  72.     Else
  73.         Roman$ = R$(v) 'Table lookup
  74.     End If
  75.     Exit Function 'below is nice condensed data Ashish uses same method as Euklides but condensed beautifully
  76.     Data 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"
  77.  
  78. Sub Split (SplitMeString As String, delim As String, loadMeArray() As String)
  79.     Dim curpos As Long, arrpos As Long, LD As Long, dpos As Long 'fix use the Lbound the array already has
  80.     curpos = 1: arrpos = LBound(loadMeArray): LD = Len(delim)
  81.     dpos = InStr(curpos, SplitMeString, delim)
  82.     Do Until dpos = 0
  83.         loadMeArray(arrpos) = Mid$(SplitMeString, curpos, dpos - curpos)
  84.         arrpos = arrpos + 1
  85.         If arrpos > UBound(loadMeArray) Then ReDim _Preserve loadMeArray(LBound(loadMeArray) To UBound(loadMeArray) + 1000) As String
  86.         curpos = dpos + LD
  87.         dpos = InStr(curpos, SplitMeString, delim)
  88.     Loop
  89.     loadMeArray(arrpos) = Mid$(SplitMeString, curpos)
  90.     ReDim _Preserve loadMeArray(LBound(loadMeArray) To arrpos) As String 'get the ubound correct
  91.  
  92.  

Offline George McGinn

  • Global Moderator
  • Forum Regular
  • Posts: 210
    • View Profile
    • Resume
Re: Roman Numeral / Decimal Number converter
« Reply #3 on: September 05, 2021, 09:40:04 pm »
Here is one I wrote back in 2019, originally in TechBASIC (iPad).

I also thought I posted one for QB64 as well. If not, here is my version, a bit more simplified but still works.

Code: QB64: [Select]
  1. _TITLE "Roman Numeral Decode.bas"
  2. ' Roman Numeral Decode.bas    Version 1.0  05/23/2019
  3. '-------------------------------------------------------------------------
  4. '       PROGRAM: Roman Numeral Decode.bas
  5. '        AUTHOR: George McGinn
  6. '
  7. '  DATE WRITTEN: 05/23/2019
  8. '       VERSION: 1.0
  9. '       PROJECT: Rosetta Code Challenge
  10. '
  11. '   DESCRIPTION: Decode Roman Numerals to Decimal Values
  12. '
  13. ' Written by George McGinn
  14. ' Version 1.0 - Created 05/23/2019
  15. '
  16. '
  17. ' CHANGE LOG
  18. '-------------------------------------------------------------------------
  19. ' 05/23/2019 v1.0 GJM - New Program.
  20. '-------------------------------------------------------------------------
  21. '
  22.  
  23.  
  24. Main:
  25. '------------------------------------------------
  26. ' CALLS THE romToDec FUNCTION WITH THE ROMAN
  27. ' NUMERALS AND RETURNS ITS DECIMAL EQUIVELENT.
  28. '
  29.    
  30.     PRINT "MDCCIV  = "; romToDec("MDCCIV") '1704
  31.     PRINT "MCMXC   = "; romToDec("MCMXC") '1990
  32.     PRINT "MMVIII  = "; romToDec("MMVIII") '2008
  33.     PRINT "MDCLXVI = "; romToDec("MDCLXVI") '1666
  34.     PRINT: PRINT
  35.     PRINT "Here are other solutions not from the TASK:"
  36.     PRINT "MCMXCIX = "; romToDec("MCMXCIX") '1999
  37.     PRINT "XXV     = "; romToDec("XXV") '25
  38.     PRINT "CMLIV   = "; romToDec("CMLIV") '954
  39.     PRINT "MMXI    = "; romToDec("MMXI") '2011
  40.     PRINT: PRINT
  41.     PRINT "Without error checking, this is also wrong. Gives 2011. Should be 2013."
  42.     PRINT "MMIIIX  = "; romToDec("MMIIIX") 'INVAID, 2011, by rules should be 2013
  43.  
  44.     END
  45.  
  46.  
  47. FUNCTION romToDec (roman AS STRING)
  48. '------------------------------------------------------
  49. ' FUNCTION THAT CONVERTS ANY ROMAN NUMERAL TO A DECIMAL
  50. '
  51. prenum = 0: num = 0
  52. LN = LEN(roman)
  53. FOR i = LN TO 1 STEP -1
  54.     x$ = MID$(roman, i, 1)
  55.     n = 1000
  56.     SELECT CASE x$
  57.         CASE "M": n = n / 1
  58.         CASE "D": n = n / 2
  59.         CASE "C": n = n / 10
  60.         CASE "L": n = n / 20
  61.         CASE "X": n = n / 100
  62.         CASE "V": n = n / 200
  63.         CASE "I": n = n / n
  64.         CASE ELSE: n = 0
  65.     END SELECT
  66.     IF n < prenum THEN num = num - n ELSE num = num + n
  67.     prenum = n
  68.  
  69. romToDec = num
  70.  
____________________________________________________________________
George McGinn
Theoretical/Applied Computer Scientist
Member: IEEE, IEEE Computer Society
Technical Council on Software Engineering
IEEE Standards Association
American Association for the Advancement of Science (AAAS)