Author Topic: Decimal to roman numbers converter  (Read 10582 times)

0 Members and 1 Guest are viewing this topic.

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: Decimal to roman numbers converter
« Reply #15 on: August 30, 2020, 02:27:18 am »
A single page table of Roman numerals for decoding movie copyrite years.

Code: QB64: [Select]
  1. DEFINT A-Z
  2. DIM er$(30), ev(30)
  3. FOR i = 1 TO 29
  4.     READ ev(i), er$(i)
  5. r = 1: c = 1
  6. FOR d = 1920 TO 2039
  7.     d$ = LTRIM$(STR$(d))
  8.     t$ = ""
  9.     FOR i = 1 TO LEN(d$)
  10.         c$ = MID$(d$, i, 1)
  11.         t = VAL(c$) * (10 ^ (LEN(d$) - i))
  12.         FOR j = 1 TO 29
  13.             IF ev(j) = t THEN t$ = t$ + er$(j)
  14.         NEXT j
  15.     NEXT i
  16.     LOCATE r, c: PRINT d$; " "; t$;
  17.     r = r + 1
  18.     IF r > 24 THEN
  19.         r = 1
  20.         c = c + 16
  21.     END IF
  22.  
  23. table:
  24. DATA 1,I
  25. DATA 2,II
  26. DATA 3,III
  27. DATA 4,IV
  28. DATA 5,V
  29. DATA 6,VI
  30. DATA 7,VII
  31. DATA 8,IIX
  32. DATA 9,IX
  33. DATA 10,X
  34. DATA 20,XX
  35. DATA 30,XXX
  36. DATA 40,XL
  37. DATA 50,L
  38. DATA 60,LX
  39. DATA 70,LXX
  40. DATA 80,XXC
  41. DATA 90,XC
  42. DATA 100,C
  43. DATA 200,CC
  44. DATA 300,CCC
  45. DATA 400,CD
  46. DATA 500,D
  47. DATA 600,DC
  48. DATA 700,DCC
  49. DATA 800,CCM
  50. DATA 900,CM
  51. DATA 1000,M
  52. DATA 2000,MM
  53.  
It works better if you plug it in.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Decimal to roman numbers converter
« Reply #16 on: August 30, 2020, 03:36:40 am »
Here's my little go at this conversion process:

Code: QB64: [Select]
  1. DIM Symbols(1 TO 3) AS STRING, Values(0 TO 3999) AS STRING
  2. Symbols(1) = "IXCM" 'Symbols is a string array to hold the symbols of our roman numerals
  3. Symbols(2) = "VLD "
  4. Symbols(3) = "XCM "
  5.  
  6. FOR I = 0 TO 3999 'here, we build our roman numerals from 0 to 3999 and store them in an array.
  7.     t$ = _TRIM$(STR$(I))
  8.     FOR k = 1 TO LEN(t$)
  9.         t = ASC(t$, k) - 48: j = LEN(t$) - k + 1
  10.         d$ = ""
  11.         SELECT EVERYCASE t
  12.             CASE 1 TO 4: d$ = d$ + MID$(Symbols(1), j, 1)
  13.             CASE 2 TO 3: d$ = d$ + MID$(Symbols(1), j, 1)
  14.             CASE 3: d$ = d$ + MID$(Symbols(1), j, 1)
  15.             CASE 4 TO 8: d$ = d$ + MID$(Symbols(2), j, 1)
  16.             CASE 6 TO 9: d$ = d$ + MID$(Symbols(1), j, 1)
  17.             CASE 7 TO 8: d$ = d$ + MID$(Symbols(1), j, 1)
  18.             CASE 8: d$ = d$ + MID$(Symbols(1), j, 1)
  19.             CASE 9: d$ = d$ + MID$(Symbols(3), j, 1)
  20.         END SELECT
  21.         Values(I) = Values(I) + d$
  22.     NEXT
  23.  
  24. l = 1: PRINT " = ";
  25. DO 'here we use a custom input routine to get the users value and show its conversion
  26.     t$ = INPUT$(1)
  27.     SELECT CASE t$
  28.         CASE "0" TO "9": v$ = v$ + t$
  29.         CASE CHR$(27): SYSTEM
  30.         CASE CHR$(8): v$ = LEFT$(v$, LEN(v$) - 1)
  31.         CASE CHR$(13): l = l + 1: v$ = "": IF l > _HEIGHT - 1 THEN PRINT: l = _HEIGHT - 1
  32.     END SELECT
  33.     LOCATE l, 1: PRINT "                                           ";
  34.     LOCATE l, 1: PRINT v$; " = ";
  35.     v = VAL(v$)
  36.     IF v < 4000 THEN
  37.         PRINT Values(v);
  38.     ELSE
  39.         PRINT "Invalid value for this program.";
  40.     END IF
  41.     _DISPLAY
  42.  

This has your custom input routine that you were wanting, so you can use ESC at any time to quit, as well as on-the-fly conversion and array storage of our values.  What I'm doing here  is simply building an array with all the values from 0 to 3999, and then creating all the roman numerals and putting them in the array, for ease of future reference.  If you want to know what the roman numeral value is for 123, all you need to do is PRINT Values(123).

For a reverse conversion routine, all one would have to do is allow the user to input symbols (IVXCLDM), and then when the value is 0, check to see if the entered string matches any of the valid roman numerals we built.  If so, then print the matching value, else print the error message..  I didn't bother to add the reverse conversion, as it's getting to be this old man's bedtime, but if someone wants it, and doesn't want to add it themselves, just toss me a message and I'll add in the functionality tomorrow.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #17 on: August 30, 2020, 12:15:21 pm »
Well Steve has suggested a clever way of checking proper Roman Numeral Numbers and doing the decimal conversions is interesting as well. I have never seen SELECT EVERYCASE before!

I was wondering how the following would work then I saw EVERYCASE:
Code: QB64: [Select]
  1.             CASE 1 TO 4: d$ = d$ + MID$(Symbols(1), j, 1)
  2.             CASE 2 TO 3: d$ = d$ + MID$(Symbols(1), j, 1)

Here is what I have from last night, wasted in checking RomanProper$ function, ha!
Code: QB64: [Select]
  1. _TITLE "Roman2Decimal Test, enter nothing will quit test loop, there are 3 test loops." ' B+ 2020-08-29
  2. ' 2020-08-29 how to go the other way? Decimal2Roman$
  3. ' RomanProper$ confirms a proper Roman Numeral with Y for Yes else error message.
  4.  
  5.     PRINT "                 *** Testing the RomanProper$ function ***"
  6.     PRINT "    Please enter a funky Roman Numeral to see if we can catch what is wrong,"
  7.     PRINT "        or enter a good one and see if we can catch it being right :)"
  8.     PRINT
  9.     INPUT " Enter test: "; test$
  10.     IF test$ = "" THEN EXIT DO
  11.     returned$ = RomanProper$(test$)
  12.     IF returned$ = "Y" THEN
  13.         PRINT "        The RomanProper$ function detected no erors for "; test$
  14.     ELSE
  15.         PRINT SPACE$(5) + returned$
  16.     END IF
  17.     PRINT
  18.  
  19.     PRINT "       *** Testing the Decimal2Roman$ function ***"
  20.     INPUT " Enter a number (1 to 3999) to convert to Roman Numerals "; test
  21.     IF test = 0 THEN EXIT DO
  22.     convert$ = Decimal2Roman$(test)
  23.     PRINT "The converter says that should be: "; convert$
  24.     PRINT
  25.  
  26.     PRINT "            *** Testing the Roman2Decimal% function ***"
  27.     PRINT " Enter a number (1 to 3999) in Roman Numerals to test proper conversion: "
  28.     PRINT
  29.     INPUT " Enter test string "; test$
  30.     IF test$ = "" THEN EXIT DO
  31.     convert = Roman2Decimal%(test$)
  32.     PRINT "The converter says that was: "; convert
  33.     PRINT
  34.  
  35. FUNCTION Roman2Decimal% (rS$) 'Caution: no checks for Roman syntax
  36.     STATIC Roman$, rV(1 TO 7) AS INTEGER
  37.     IF rV(7) <> 1000 THEN 'do once and for all time
  38.         Roman$ = "IVXLCDM"
  39.         FOR i = 1 TO 7
  40.             IF i MOD 2 = 0 THEN rV(i) = 5 * 10 ^ (i / 2 - 1) ELSE rV(i) = 10 ^ ((i - 1) / 2)
  41.         NEXT
  42.     END IF
  43.     'now for the current call
  44.     FOR i = 1 TO LEN(rS$)
  45.         lv = rV(INSTR(Roman$, MID$(rS$, i, 1)))
  46.         IF i <> LEN(rS$) THEN
  47.             lv2 = rV(INSTR(Roman$, MID$(rS$, i + 1, 1)))
  48.             IF lv2 > lv THEN lv = -lv
  49.         END IF
  50.         convert = convert + lv
  51.     NEXT
  52.     Roman2Decimal% = convert
  53.  
  54. FUNCTION Decimal2Roman$ (d AS INTEGER) ' 1 to 3999
  55.     cd = d 'make copy because changing
  56.     STATIC Ones$(1 TO 10), Tens$(1 TO 10), H100s$(1 TO 10)
  57.     IF Ones$(10) = "" THEN 'setup our arrays
  58.         Ones$(1) = "I": Ones$(2) = "II": Ones$(3) = "III": Ones$(4) = "IV": Ones$(5) = "V"
  59.         Ones$(6) = "VI": Ones$(7) = "VII": Ones$(8) = "VIII": Ones$(9) = "IX": Ones$(10) = "X"
  60.         FOR i = 1 TO 10
  61.             Tens$(i) = strReplace$(Ones$(i), "X", "C")
  62.             Tens$(i) = strReplace$(Tens$(i), "I", "X")
  63.             Tens$(i) = strReplace$(Tens$(i), "V", "L")
  64.             H100s$(i) = strReplace$(Ones$(i), "X", "M")
  65.             H100s$(i) = strReplace$(H100s$(i), "I", "C")
  66.             H100s$(i) = strReplace$(H100s$(i), "V", "D")
  67.         NEXT
  68.     END IF
  69.     IF cd > 1000 THEN convert$ = STRING$(INT(cd / 1000), "M"): cd = cd - 1000 * INT(cd / 1000)
  70.     IF cd > 100 THEN convert$ = convert$ + H100s$(INT(cd / 100)): cd = cd - 100 * INT(cd / 100)
  71.     IF cd > 10 THEN convert$ = convert$ + Tens$(INT(cd / 10)): cd = cd - 10 * INT(cd / 10)
  72.     IF cd >= 1 THEN convert$ = convert$ + Ones$(cd)
  73.     Decimal2Roman$ = convert$
  74.  
  75. FUNCTION strReplace$ (s$, replace$, new$) 'case sensitive  2020-07-28 version
  76.     DIM p AS LONG, sCopy$, LR AS INTEGER, lNew AS INTEGER
  77.     IF LEN(s$) = 0 OR LEN(replace$) = 0 THEN
  78.         strReplace$ = s$: EXIT FUNCTION
  79.     ELSE
  80.         LR = LEN(replace$): lNew = LEN(new$)
  81.     END IF
  82.  
  83.     sCopy$ = s$ ' otherwise s$ would get changed
  84.     p = INSTR(sCopy$, replace$)
  85.     WHILE p
  86.         sCopy$ = MID$(sCopy$, 1, p - 1) + new$ + MID$(sCopy$, p + LR)
  87.         p = INSTR(p + lNew, sCopy$, replace$)
  88.     WEND
  89.     strReplace$ = sCopy$
  90.  
  91. FUNCTION RomanProper$ (test$) ' is test$ a Roman Numeral with proper syntax? Y for Yes, if No then error message.
  92.     test$ = _TRIM$(UCASE$(test$)) ' it should be OK to make this change to the argument in not in Capitals
  93.     Roman$ = "MDCLXVI": checked$ = SPACE$(7) ' 2, 4, 6 should only appear once the others up to 3 except M 4 max
  94.     FOR i = 1 TO LEN(test$)
  95.         L$ = MID$(test$, i, 1)
  96.         p = INSTR(Roman$, L$)
  97.         IF i <> LEN(test$) THEN nextL$ = MID$(test$, i + 1, 1) ELSE nextL$ = ""
  98.  
  99.         IF p = 0 THEN RomanProper$ = "Error: wrong character in string.": EXIT SUB
  100.         IF p MOD 2 = 0 THEN
  101.             IF L$ = "V" THEN
  102.                 IF nextL$ <> "" AND nextL$ <> "I" THEN RomanProper$ = "Error: out of order.": EXIT SUB
  103.             ELSEIF L$ = "L" THEN
  104.                 IF nextL$ <> "" AND nextL$ <> "I" AND nextL$ <> "V" AND nextL$ <> "X" THEN RomanProper$ = "Error: out of order.": EXIT SUB
  105.                 IF lastL$ = "I" THEN RomanProper$ = "Error: out of order.": EXIT SUB
  106.             ELSEIF L$ = "D" THEN
  107.                 IF nextL$ = "M" THEN RomanProper$ = "Error: out of order.": EXIT SUB
  108.                 IF lastp > p AND lastL$ <> "C" THEN RomanProper$ = "Error: out of order.": EXIT SUB
  109.             END IF
  110.             IF MID$(checked$, p, 1) = " " THEN
  111.                 MID$(checked$, p, 1) = "1"
  112.             ELSE
  113.                 RomanProper$ = "Error: too many " + L$ + "'s.": EXIT SUB
  114.             END IF
  115.         ELSE ' p mod 2 = 1
  116.             vM = VAL(MID$(checked$, p, 1))
  117.             IF L$ = "M" THEN
  118.                 IF (lastL$ <> "M" AND lastL$ <> "C") AND lastL$ <> "" THEN RomanProper$ = "Error: " + L$ + " out of order.": EXIT SUB
  119.                 IF vM > 3 THEN RomanProper$ = "Error: too many " + L$ + "'s.": EXIT SUB
  120.                 MID$(checked$, p, 1) = _TRIM$(STR$(vM + 1))
  121.             ELSEIF L$ = "C" THEN
  122.                 IF lastL$ = "L" OR lastL$ = "V" OR lastL$ = "I" THEN RomanProper$ = "Error: " + L$ + " out of order.": EXIT SUB
  123.                 IF vM > 2 THEN RomanProper$ = "Error: too many " + L$ + "'s.": EXIT SUB
  124.                 MID$(checked$, p, 1) = _TRIM$(STR$(vM + 1))
  125.             ELSEIF L$ = "X" THEN
  126.                 IF MID$(checked$, 6, 1) = "1" OR VAL(MID$(checked$, 7, 1)) > 1 THEN RomanProper$ = "Error: " + L$ + " out of order.": EXIT SUB
  127.                 IF vM > 2 THEN RomanProper$ = "Error: too many " + L$ + "'s.": EXIT SUB
  128.                 MID$(checked$, p, 1) = _TRIM$(STR$(vM + 1))
  129.             ELSEIF L$ = "I" THEN 'can follow any letter
  130.                 IF vM > 2 THEN RomanProper$ = "Error: too many " + L$ + "'s.": EXIT SUB
  131.                 MID$(checked$, p, 1) = _TRIM$(STR$(vM + 1))
  132.             END IF
  133.         END IF
  134.         lastp = p
  135.         lastL$ = L$
  136.     NEXT
  137.     'still here?
  138.     RomanProper$ = "Y" 'then must be OK
  139.  
  140.  
  141.  

Just to see, I will rewrite this with Steve's idea for check of RomanProper$ and a more straightforward way for decimal2Roman$.
« Last Edit: August 30, 2020, 01:08:53 pm by bplus »

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Decimal to roman numbers converter
« Reply #18 on: August 30, 2020, 01:00:02 pm »
Quote
I was wondering how the following would work the I saw EVERYCASE:
            CASE 1 TO 4: d$ = d$ + MID$(Symbols(1), j, 1)
            CASE 2 TO 3: d$ = d$ + MID$(Symbols(1), j, 1)

My idea was this one:

Each 10's digit is basically made up of 3 symbols.

Numbers 1-10 use I, V, X
Numbers 10 - 100 use X, L, C
Numbers 100 - 1000 use C, D, M

The pattern we generate is always the same:
1 = 1st symbol
2 = double 1st symbol
3 = triple 1st symbol
4 = 1st symbol + 2nd symbol
And so on...

So 3 is III.  30 is XXX.  300 is CCC...  Same logic pattern, just different symbols based on the 10's position.  That's where the DIM Symbols(1 TO 3) array comes from, and represents.

The SELECT EVERY CASE just builds our symbols, to match our values.
CASE 1 TO 4 -- This says we need the first symbol that matches our 10s position, if our number  is from 1 to 4.
CASE 2 TO 3 -- does the same, if our number is a 2 or a 3.
CASE 3 -- same, but only if the value is 3.

So if my number is 2, the first case is valid, the second case is valid, but the third case isn't...  We build the number II, XX, CC, depending on our 10's position.

So for 22, we just build our value with the XX and then the II, making the answer XXII.



Basically, the SELECT EVERYCASE can be considered to be nothing more than a row of IF statements, all with the same comparison value.  The above could also be written as:

IF X >= 1 AND X <= 4 THEN... Do stuff
IF X >= 2 AND X <= 3 THEN... Do stuff
IF X = 3 THEN... Do stuff

« Last Edit: August 30, 2020, 01:37:08 pm by SMcNeill »
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #19 on: August 30, 2020, 01:12:28 pm »
@SMcNeill That's very cool pattern recognition!

And what a great demo of EVERYCASE!

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Decimal to roman numbers converter
« Reply #20 on: August 30, 2020, 01:27:15 pm »
And here's the same routine, working in converting in both directions, as far as I can tell.

Code: QB64: [Select]
  1. DIM Symbols(1 TO 3) AS STRING, Values(0 TO 3999) AS STRING
  2. Symbols(1) = "IXCM" 'Symbols is a string array to hold the symbols of our roman numerals
  3. Symbols(2) = "VLD "
  4. Symbols(3) = "XCM "
  5.  
  6. FOR I = 0 TO 3999 'here, we build our roman numerals from 0 to 3999 and store them in an array.
  7.     t$ = _TRIM$(STR$(I))
  8.     FOR k = 1 TO LEN(t$)
  9.         t = ASC(t$, k) - 48: j = LEN(t$) - k + 1
  10.         d$ = ""
  11.         SELECT EVERYCASE t
  12.             CASE 1 TO 4: d$ = d$ + MID$(Symbols(1), j, 1)
  13.             CASE 2 TO 3: d$ = d$ + MID$(Symbols(1), j, 1)
  14.             CASE 3: d$ = d$ + MID$(Symbols(1), j, 1)
  15.             CASE 4 TO 8: d$ = d$ + MID$(Symbols(2), j, 1)
  16.             CASE 6 TO 9: d$ = d$ + MID$(Symbols(1), j, 1)
  17.             CASE 7 TO 8: d$ = d$ + MID$(Symbols(1), j, 1)
  18.             CASE 8: d$ = d$ + MID$(Symbols(1), j, 1)
  19.             CASE 9: d$ = d$ + MID$(Symbols(3), j, 1)
  20.         END SELECT
  21.         Values(I) = Values(I) + d$
  22.     NEXT
  23.  
  24. l = 1: PRINT " = ";
  25. DO 'here we use a custom input routine to get the users value and show its conversion
  26.     t$ = INPUT$(1)
  27.     SELECT CASE UCASE$(t$)
  28.         CASE "0" TO "9", "I", "X", "V", "C", "D", "L", "M": v$ = v$ + UCASE$(t$)
  29.         CASE CHR$(27): SYSTEM
  30.         CASE CHR$(8): v$ = LEFT$(v$, LEN(v$) - 1)
  31.         CASE CHR$(13): l = l + 1: v$ = "": IF l > _HEIGHT - 1 THEN PRINT: l = _HEIGHT - 1
  32.     END SELECT
  33.     LOCATE l, 1: PRINT "                                           ";
  34.     LOCATE l, 1: PRINT v$; " = ";
  35.     v = VAL(v$)
  36.     IF v = 0 THEN
  37.         FOR I = 0 TO 3999
  38.             IF v$ = Values(I) THEN PRINT I;: EXIT FOR
  39.         NEXT
  40.         IF I = 4000 THEN PRINT "Invalid value for this program.";
  41.     ELSEIF v < 4000 THEN
  42.         PRINT Values(v);
  43.     ELSE
  44.         PRINT "Invalid value for this program.";
  45.     END IF
  46.     _DISPLAY
  47.  

For less than 50 lines of code, I think it's about as simple as one can get for a decimal-to-roman-to-decimal conversion program.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #21 on: August 30, 2020, 03:15:17 pm »
And here is handy 40 line SUB you can plug into any program and use to translate, to or from, Roman Numerals 1 to 3999 along with error messages if it can't do a translation.

Code: QB64: [Select]
  1. _TITLE "Roman SUB Test" ' B+ 2020-08-30 rewrite old to one sub, using several hints from SMcNeill
  2.     PRINT " Testing conversion of numbers 1 to 3999 to or from Roman Numerals >"
  3.     INPUT " Enter a string to test "; test$
  4.     Roman test$, return$
  5.     PRINT " The Roman SUB returned: "; return$
  6.     PRINT
  7. LOOP UNTIL test$ = ""
  8.  
  9. SUB Roman (inStr$, outStr$) ' 1 to 3999
  10.     STATIC Ones$(1 TO 10), Tens$(1 TO 10), H100s$(1 TO 10), R$(1 TO 3999)
  11.     IF Ones$(10) = "" THEN 'setup our arrays
  12.         Ones$(1) = "I": Ones$(2) = "II": Ones$(3) = "III": Ones$(4) = "IV": Ones$(5) = "V"
  13.         Ones$(6) = "VI": Ones$(7) = "VII": Ones$(8) = "VIII": Ones$(9) = "IX": Ones$(10) = "X"
  14.         Tens$(1) = "X": Tens$(2) = "XX": Tens$(3) = "XXX": Tens$(4) = "XL": Tens$(5) = "L"
  15.         Tens$(6) = "LX": Tens$(7) = "LXX": Tens$(8) = "LXXX": Tens$(9) = "XC": Tens$(10) = "C"
  16.         H100s$(1) = "C": H100s$(2) = "CC": H100s$(3) = "CCC": H100s$(4) = "CD": H100s$(5) = "D"
  17.         H100s$(6) = "DC": H100s$(7) = "DCC": H100s$(8) = "DCCC": H100s$(9) = "CM": H100s$(10) = "M"
  18.         FOR i = 1 TO 3999
  19.             cd = i: convert$ = ""
  20.             IF cd > 1000 THEN convert$ = STRING$(INT(cd / 1000), "M"): cd = cd - 1000 * INT(cd / 1000)
  21.             IF cd > 100 THEN convert$ = convert$ + H100s$(INT(cd / 100)): cd = cd - 100 * INT(cd / 100)
  22.             IF cd > 10 THEN convert$ = convert$ + Tens$(INT(cd / 10)): cd = cd - 10 * INT(cd / 10)
  23.             IF cd >= 1 THEN convert$ = convert$ + Ones$(cd)
  24.             R$(i) = convert$
  25.         NEXT
  26.     END IF
  27.     s$ = _TRIM$(UCASE$(inStr$))
  28.     IF s$ = "" OR s$ = "0" THEN outStr$ = "Error: nada": EXIT SUB 'handle nothing
  29.     FOR i = 1 TO LEN(s$)
  30.         pd = INSTR("0123456789", MID$(s$, i, 1)): pr = INSTR("MDCLXVI", MID$(s$, i, 1))
  31.         IF pd = 0 AND pr = 0 THEN outStr$ = "Error: unknown character.": EXIT SUB 'handle wrong alpha
  32.         IF i > 1 THEN 'check for mixed messages
  33.             IF (lastpd = 0 AND pd > 0) OR (lastpr = 0 AND pr > 0) THEN outStr$ = "Error: digits mixed with letters.": EXIT SUB
  34.         END IF
  35.         lastpd = pd: lastpr = pr
  36.     NEXT
  37.     v = VAL(s$)
  38.     IF v = 0 THEN
  39.         FOR i = 1 TO 3999
  40.             IF R$(i) = s$ THEN outStr$ = _TRIM$(STR$(i)): EXIT SUB
  41.         NEXT
  42.         outStr$ = "Error: Invalid Roman Numeral? string."
  43.     ELSEIF v > 0 AND v < 4000 THEN
  44.         outStr$ = R$(v)
  45.     ELSE
  46.         outStr$ = "Error: Not in range of 1 to 3999."
  47.     END IF
  48.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #22 on: August 31, 2020, 12:56:28 am »
Code: QB64: [Select]
  1.  

What???
 
Oh, ha it's supposed to be inStr$ but the forum editor changed it to a keyword even when it had the $.

I wondered because it was capitalizing and trimming leading space when I tested.

Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Re: Decimal to roman numbers converter
« Reply #23 on: August 31, 2020, 02:44:29 am »
I understand half the things you guys say, but I still working on the function. So far i made a lot of progress in the user interface
Some matrix-DOS-style
Code: QB64: [Select]
  1. '--------------* Setup *--------------
  2. DATA "","I","II","III","IV","V","VI","VII","VIII","IX","","X","XX","XXX","XL","L","LX","LXX","LXXX","XC","","C","CC","CCC","CD","D","DC","DCC","DCCC","CM","","M","MM","MMM"
  3.  
  4. DIM SHARED resultPieces$(3, 9)
  5.  
  6. FOR i% = 0 TO 3
  7.     IF i% < 3 THEN
  8.         FOR ii% = 0 TO 9
  9.             READ resultPieces$(i%, ii%)
  10.         NEXT ii%
  11.     ELSE
  12.         FOR ii% = 0 TO 3
  13.             READ resultPieces$(i%, ii%)
  14.         NEXT ii%
  15.     END IF
  16. NEXT i%
  17.  
  18. SCREEN _NEWIMAGE(250, 96, 32)
  19. CONST WHITE = _RGB32(255, 255, 255)
  20. CONST YELLOW = _RGB32(255, 255, 0)
  21. CONST RED = _RGB32(255, 0, 0)
  22. CONST GREEN = _RGB32(0, 255, 0)
  23. CONST LIGHTGRAY = _RGB32(127, 127, 127)
  24. CONST DARKGRAY = _RGB32(63, 63, 63)
  25.  
  26. _TITLE "Arabic/Roman Conversor"
  27.  
  28. DIM actualMenuWorking%
  29. DIM menuHighlight%
  30.  
  31.  
  32. DIM KeyPress$
  33.  
  34. actualMenuWorking% = 0
  35. menuHighlight% = 1
  36.  
  37. '--------------* Program V1.2 *--------------
  38. sayHello
  39.     DO
  40.         KeyPress$ = INKEY$
  41.         _LIMIT 30
  42.         SELECT CASE actualMenuWorking%
  43.             CASE 0: printMainMenu
  44.             CASE 1: arabicToRoman
  45.             CASE 2: romanToArabic
  46.             CASE -1: sayGoodbye
  47.         END SELECT
  48.     LOOP UNTIL KeyPress$ <> ""
  49.  
  50.     IF KeyPress$ = CHR$(13) THEN
  51.         SELECT CASE menuHighlight%
  52.             CASE 1: actualMenuWorking% = 1
  53.             CASE 2: actualMenuWorking% = 2
  54.             CASE 3: actualMenuWorking% = -1
  55.         END SELECT
  56.     ELSEIF KeyPress$ = CHR$(0) + "H" THEN
  57.         IF menuHighlight% <> 1 THEN menuHighlight% = menuHighlight% - 1
  58.     ELSEIF KeyPress$ = CHR$(0) + "P" THEN
  59.         IF menuHighlight% <> 3 THEN menuHighlight% = menuHighlight% + 1
  60.     ELSEIF KeyPress$ = CHR$(27) THEN
  61.         menuHighlight% = 3
  62.     END IF
  63.  
  64.  
  65.  
  66. '--------------* Functions *--------------
  67. FUNCTION turnIntegerToRoman$ (inputNumber%)
  68.  
  69.     numberAsString$ = LTRIM$(STR$(inputNumber%))
  70.     IF inputNumber% > 0 AND inputNumber% < 4000 THEN
  71.         digits% = LEN(numberAsString$)
  72.         REDIM tmpArray%(digits%)
  73.         REDIM subResult$(digits%)
  74.         FOR i% = 0 TO digits% - 1
  75.             tmpArray%(i%) = VAL(MID$(numberAsString$, digits% - i%, 1))
  76.             subResult$(i%) = resultPieces$(i%, tmpArray%(i%))
  77.             result$ = subResult$(i%) + result$
  78.         NEXT i%
  79.         COLOR GREEN
  80.         turnIntegerToRoman$ = result$
  81.     ELSE
  82.         COLOR RED
  83.         turnIntegerToRoman$ = "I can't convert " + numberAsString$
  84.     END IF
  85.  
  86.  
  87. '- - - - - - - - - - - - - - - - - - - - - -
  88. FUNCTION turnRomanToInteger$ (inputRoman$) ' in process
  89.  
  90.     DIM subResult$
  91.     subResult$ = ""
  92.  
  93.     FOR i% = 3 TO 0 STEP -1
  94.         IF i% = 3 THEN
  95.             FOR ii% = 3 TO 0 STEP -1
  96.                 IF INSTR(inputRoman$, resultPieces$(i%, ii%)) THEN
  97.                     subResult$ = subResult$ + LTRIM$(STR$(ii%))
  98.                     EXIT FOR
  99.                 END IF
  100.             NEXT ii%
  101.         ELSE
  102.             FOR ii% = 9 TO 0 STEP -1
  103.                 IF INSTR(inputRoman$, resultPieces$(i%, ii%)) THEN
  104.                     subResult$ = subResult$ + LTRIM$(STR$(ii%))
  105.                     EXIT FOR
  106.                 END IF
  107.             NEXT ii%
  108.         END IF
  109.     NEXT i%
  110.  
  111.     IF subResult$ <> "" THEN
  112.         COLOR GREEN
  113.         turnRomanToInteger$ = subResult$
  114.     ELSE
  115.         COLOR RED
  116.         turnRomanToInteger$ = "Not a roman!"
  117.     END IF
  118.  
  119.  
  120. '--------------* Subroutines *--------------
  121. SUB sayHello ()
  122.  
  123.     helloMessage1$ = "         Hello master"
  124.     helloMessage2$ = "  Order me and i will obey..."
  125.  
  126.     COLOR GREEN
  127.  
  128.     i% = 0
  129.     DO
  130.         _DELAY .05
  131.         i% = i% + 1
  132.         buildingMessage$ = LEFT$(helloMessage1$, i%) + CHR$(219)
  133.         LOCATE 3, 1
  134.         PRINT buildingMessage$
  135.     LOOP UNTIL LEN(buildingMessage$) = LEN(helloMessage1$) + 1
  136.     LOCATE CSRLIN - 1, LEN(helloMessage1$) + 1: PRINT " "
  137.  
  138.     i% = 0
  139.     DO
  140.         _DELAY .05
  141.         i% = i% + 1
  142.         buildingMessage$ = LEFT$(helloMessage2$, i%) + CHR$(219)
  143.         LOCATE 4, 1
  144.         PRINT buildingMessage$
  145.     LOOP UNTIL LEN(buildingMessage$) = LEN(helloMessage2$) + 1
  146.     LOCATE CSRLIN - 1, LEN(helloMessage2$) + 1: PRINT " "
  147.  
  148.     SLEEP 2
  149.     CLS
  150.  
  151.  
  152. '- - - - - - - - - - - - - - - - - - - - - -
  153. SUB printMainMenu ()
  154.  
  155.     SHARED menuHighlight%
  156.  
  157.     CLS
  158.  
  159.     LOCATE 1, 1
  160.     COLOR WHITE
  161.     PRINT "     Roman/Arabic Conversor";
  162.     LOCATE 2, 1
  163.     PRINT SPACE$(5);: PRINT STRING$(22, CHR$(223));
  164.  
  165.     IF menuHighlight% = 1 THEN
  166.         COLOR YELLOW
  167.         LOCATE 3, 7
  168.         PRINT CHR$(26);: PRINT SPACE$(16);: PRINT CHR$(27);
  169.     ELSE
  170.         COLOR DARKGRAY
  171.     END IF
  172.     LOCATE 3, 9
  173.     PRINT "Arabic  Roman";
  174.  
  175.     IF menuHighlight% = 2 THEN
  176.         COLOR YELLOW
  177.         LOCATE 4, 7
  178.         PRINT CHR$(26);: PRINT SPACE$(16);: PRINT CHR$(27);
  179.     ELSE
  180.         COLOR DARKGRAY
  181.     END IF
  182.     LOCATE 4, 9
  183.     PRINT "Roman  Arabic";
  184.  
  185.     IF menuHighlight% = 3 THEN
  186.         COLOR YELLOW
  187.         LOCATE 5, 12
  188.         PRINT CHR$(26);: PRINT SPACE$(6);: PRINT CHR$(27);
  189.     ELSE
  190.         COLOR DARKGRAY
  191.     END IF
  192.     LOCATE 5, 14
  193.     PRINT "Exit";
  194.  
  195.     COLOR WHITE
  196.     LOCATE 6, 1
  197.     PRINT " UP-DOWN select / ENTER choose";
  198.  
  199.     _DISPLAY
  200.  
  201.  
  202. '- - - - - - - - - - - - - - - - - - - - - -
  203. SUB arabicToRoman ()
  204.  
  205.     SHARED actualMenuWorking%
  206.  
  207.     subInput$ = ""
  208.     num% = 0
  209.  
  210.     DO
  211.         DO
  212.             CLS
  213.             COLOR WHITE
  214.             LOCATE 1, 1
  215.             PRINT "Give me a number from 1 to 3999"
  216.             PRINT "     Press ESC to go back"
  217.             PRINT "          > ";: PRINT subInput$ + CHR$(95)
  218.             PRINT
  219.             PRINT num%; "= "; turnIntegerToRoman$(num%);
  220.             KeyPress$ = INKEY$
  221.             _LIMIT 40
  222.             _DISPLAY
  223.         LOOP UNTIL KeyPress$ <> ""
  224.  
  225.         'NUMBERS
  226.         IF (ASC(KeyPress$) > 47 AND ASC(KeyPress$) < 58) THEN 'if NUMBER pressed and the subInput$ is not longer
  227.             IF LEN(subInput$) < 4 THEN subInput$ = subInput$ + KeyPress$ '    than 4 then increase the subInput$
  228.  
  229.             'BACKSPACE
  230.         ELSEIF KeyPress$ = CHR$(8) THEN '                   if BACKSPACE pressed and subInput ain't null
  231.             IF subInput$ <> "" THEN subInput$ = LEFT$(subInput$, LEN(subInput$) - 1) 'one less character
  232.  
  233.             ' ENTER
  234.         ELSEIF KeyPress$ = CHR$(13) THEN '  if ENTER pressed and
  235.             IF subInput$ <> "" THEN '       subInput$ ain't null then
  236.                 num% = VAL(subInput$) '     turn to a value and save it to num%
  237.                 subInput$ = "" '            and clear subInput$
  238.             END IF
  239.         END IF
  240.  
  241.         'ESC
  242.     LOOP UNTIL KeyPress$ = CHR$(27)
  243.     actualMenuWorking% = 0
  244.  
  245.  
  246. '- - - - - - - - - - - - - - - - - - - - - -
  247. SUB romanToArabic ()
  248.  
  249.     SHARED actualMenuWorking%
  250.  
  251.     subInput$ = ""
  252.     lastInput$ = "I"
  253.  
  254.     DO
  255.         DO
  256.             CLS
  257.             COLOR WHITE
  258.             LOCATE 1, 1
  259.             PRINT "Give me a number from 1 to 3999"
  260.             PRINT "     Press ESC to go back"
  261.             PRINT "      > ";: PRINT subInput$ + CHR$(95)
  262.             PRINT
  263.             PRINT " "; lastInput$; "= "; turnRomanToInteger$(lastInput$);
  264.             KeyPress$ = INKEY$
  265.             _LIMIT 40
  266.             _DISPLAY
  267.         LOOP UNTIL KeyPress$ <> ""
  268.  
  269.         'LETTERS
  270.         IF LEN(subInput$) < 15 THEN ' if roman not longer than 15 (MMMDCCCLXXXVIII)
  271.             SELECT CASE ASC(KeyPress$) ' only valid letters
  272.                 CASE 73 OR 105: subInput$ = subInput$ + KeyPress$ ' I
  273.                 CASE 86 OR 118: subInput$ = subInput$ + KeyPress$ ' V
  274.                 CASE 88 OR 120: subInput$ = subInput$ + KeyPress$ ' X
  275.                 CASE 76 OR 108: subInput$ = subInput$ + KeyPress$ ' L
  276.                 CASE 67 OR 99: subInput$ = subInput$ + KeyPress$ '  C
  277.                 CASE 68 OR 100: subInput$ = subInput$ + KeyPress$ ' D
  278.                 CASE 77 OR 109: subInput$ = subInput$ + KeyPress$ ' M
  279.             END SELECT
  280.         END IF
  281.  
  282.         'BACKSPACE
  283.         IF KeyPress$ = CHR$(8) THEN ' if BACKSPACE pressen and subInput ain't null
  284.             IF subInput$ <> "" THEN subInput$ = LEFT$(subInput$, LEN(subInput$) - 1) 'one less character
  285.  
  286.             ' ENTER
  287.         ELSEIF KeyPress$ = CHR$(13) THEN '  if ENTER pressed and
  288.             IF subInput$ <> "" THEN '       subInput$ ain't null then
  289.                 lastInput$ = subInput$ '    do as user says
  290.                 subInput$ = "" '            and clear subInput$
  291.             END IF
  292.         END IF
  293.  
  294.         subInput$ = UCASE$(subInput$) ' in case user dosn't use uppers
  295.  
  296.         'ESC
  297.     LOOP UNTIL KeyPress$ = CHR$(27)
  298.     actualMenuWorking% = 0
  299.  
  300.  
  301. '- - - - - - - - - - - - - - - - - - - - - -
  302. SUB sayGoodbye ()
  303.  
  304.     CLS
  305.  
  306.     goodbyeMessage$ = "Have a nice day!"
  307.  
  308.     COLOR RED
  309.     LOCATE 3, 7
  310.     PRINT CHR$(3)
  311.     LOCATE 3, 26
  312.     PRINT CHR$(3)
  313.  
  314.     COLOR GREEN
  315.     i% = 0
  316.     DO
  317.         _DELAY .05
  318.         i% = i% + 1
  319.         buildingMessage$ = LEFT$(goodbyeMessage$, i%)
  320.         LOCATE 3, 9
  321.         PRINT buildingMessage$
  322.         _DISPLAY
  323.     LOOP UNTIL LEN(buildingMessage$) = LEN(goodbyeMessage$)
  324.  
  325.     SLEEP 2
  326.     SYSTEM
  327.  
  328.  
  329.  

If i only knew more string manipulation... I'll keep loking... some LEFT$ now, maybe...

But at least i done the Esc thing i wanted, and works cool

Nice work bplus! But i'm too newbie, i  can't easely read it yet... You loaded the DATA again? or is it like part of the SUB? i'm sorry if i sound stupid, but can u guys name variables a bit more self explainatorie? XD

I'm learning a lot with this little program! Didn't imagine that could be took so far... Thank you guys! I'll keep working!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #24 on: August 31, 2020, 03:06:21 am »
Hi @Juan Tamarit

I put the Roman symbols directly into 3 arrays: ones, tens and h100s (hundreds).

Tell you what while waiting for a Run to finish I will add more comments to my code.

Offline Juan Tamarit

  • Newbie
  • Posts: 53
    • View Profile
Re: Decimal to roman numbers converter
« Reply #25 on: August 31, 2020, 03:17:14 am »
Thank you bro, i'm really interested on what you talking, but u didn't used the original array?

Did you like the GUI i made? =) i did lit the fireworks at last hehehe

BUT STILL HAVE TO MAKE THAT FUNCTION WORKS BY MY OWN! Personal obsesion thing, you know... XD

Cheers, bro!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #26 on: August 31, 2020, 04:04:19 am »
Brother!  ;-))

I will check out your code opus when it's not 4 AM and my eyes too blurry to see.


Here are my comments as promised, read 'em and leap ;-))  (with joy from enlightenment)
Code: QB64: [Select]
  1. _TITLE "Roman SUB Test" ' B+ 2020-08-30 rewrite old to one sub, using several hints from SMcNeill
  2.  
  3.  
  4. 'I hope you can understand how this testing part works :)
  5.     PRINT " Testing conversion of numbers 1 to 3999 to or from Roman Numerals >"
  6.     INPUT " Enter a string to test "; test$
  7.  
  8.     'Here is the crucial call to the SUB we are testing.
  9.     Roman test$, RETURN$
  10.     PRINT " The Roman SUB returned: "; RETURN$
  11.     PRINT
  12. LOOP UNTIL test$ = ""
  13.  
  14.  
  15.  
  16. SUB Roman (inStr$, outStr$) ' 1 to 3999  The inStr$ variable brings in a decimal or a Roman Numeral
  17.     '                         and Roman SUB will output the conversion or an Error: message in outStr$.
  18.  
  19.     STATIC Ones$(1 TO 10), Tens$(1 TO 10), H100s$(1 TO 10), R$(1 TO 3999)
  20.     'STATIC preserves all values between calls to the SUB procedure.
  21.  
  22.  
  23.     IF Ones$(10) = "" THEN 'setup our arrays
  24.         'If Ones$(10) = "" then this is very first time this sub is called, so load up the arrays of data.
  25.  
  26.         'directly load data into the arrays without READ and DATA statements
  27.         Ones$(1) = "I": Ones$(2) = "II": Ones$(3) = "III": Ones$(4) = "IV": Ones$(5) = "V"
  28.         Ones$(6) = "VI": Ones$(7) = "VII": Ones$(8) = "VIII": Ones$(9) = "IX": Ones$(10) = "X"
  29.         Tens$(1) = "X": Tens$(2) = "XX": Tens$(3) = "XXX": Tens$(4) = "XL": Tens$(5) = "L"
  30.         Tens$(6) = "LX": Tens$(7) = "LXX": Tens$(8) = "LXXX": Tens$(9) = "XC": Tens$(10) = "C"
  31.         H100s$(1) = "C": H100s$(2) = "CC": H100s$(3) = "CCC": H100s$(4) = "CD": H100s$(5) = "D"
  32.         H100s$(6) = "DC": H100s$(7) = "DCC": H100s$(8) = "DCCC": H100s$(9) = "CM": H100s$(10) = "M"
  33.  
  34.  
  35.         'R is for Roman, the R$() array will hold all the Roman Numeral Strings from 1 to 3999.
  36.         FOR i = 1 TO 3999
  37.  
  38.             cd = i 'cd originally stood for copy decimal from original Decimal2Roman function,
  39.             '       here I just kept the name for decimal numbers.
  40.  
  41.             convert$ = "" ' I am converting the decimal number to Roman,
  42.             '               this variable is storing the building of the Roman string.
  43.  
  44.             'Building from decimal 1000's:
  45.             ' INT(cd / 1000) is how many 1000's the number cd has.
  46.             ' The STRING$ function creates repeated characters, so repeating M the number of 1000's I have.
  47.             IF cd > 1000 THEN convert$ = STRING$(INT(cd / 1000), "M")
  48.  
  49.             'Take away 1000's in build, whats left is back in cd.
  50.             cd = cd - 1000 * INT(cd / 1000)
  51.  
  52.  
  53.             'Now how many 100's do I have?  This many = INT(cd / 100). Lookup that number in h100s$() symbols.
  54.             'If it was 5 then h100s$(5) = "D", add that to my build variable convert$.
  55.             IF cd > 100 THEN convert$ = convert$ + H100s$(INT(cd / 100))
  56.  
  57.             'And sutract my 100's from cd.
  58.             cd = cd - 100 * INT(cd / 100)
  59.  
  60.             'Now how many 10's do I have?  This many = INT(cd / 10), use that number for index to Tens$() lookup symbol.
  61.             'and add it to convert$.
  62.             IF cd > 10 THEN convert$ = convert$ + Tens$(INT(cd / 10))
  63.  
  64.             'And subtract 10's from cd.
  65.             cd = cd - 10 * INT(cd / 10)
  66.  
  67.             'And finally for ones place of decimal number cd is all that remains lookup the symbol in Ones$()
  68.             'and add it to convert$.
  69.             IF cd >= 1 THEN convert$ = convert$ + Ones$(cd)
  70.  
  71.             'OK the Roman Numeral string is built in the variable convert$, save it in our big R$() array.
  72.             R$(i) = convert$
  73.         NEXT
  74.  
  75.         'we are now done with all setup and ready to start converting number by array lookups
  76.     END IF
  77.  
  78.  
  79.  
  80.     'Make a copy of instr$ it could be decimal or it could be Roman we don't know yet,
  81.     ' but we want to make sure spaces are trimmed and any letters are capitalized.
  82.     's is for string!
  83.     s$ = _TRIM$(UCASE$(inStr$))
  84.  
  85.     ' Let's get rid of trivial error cases first.
  86.     IF s$ = "" OR s$ = "0" THEN outStr$ = "Error: nada": EXIT SUB 'handle nothing
  87.  
  88.     ' Now is inStr$ all decimal digits or all Roman Letters or something that indicates an error?
  89.     FOR i = 1 TO LEN(s$)
  90.  
  91.         '  pd is for place of digit.                pr is for place of Roman Letter.
  92.         pd = INSTR("0123456789", MID$(s$, i, 1)): pr = INSTR("MDCLXVI", MID$(s$, i, 1))
  93.  
  94.         ' If both are 0 then there is a crazy character on the loose, time to bug out!
  95.         IF pd = 0 AND pr = 0 THEN outStr$ = "Error: unknown character.": EXIT SUB 'handle wrong alpha
  96.  
  97.         ' Here we compare the pd to the last pd and pr to the last pr to check for mixed messages.
  98.         ' If the current character is Roman and the last was a decimal then WTH? letters are mixed with digits.
  99.         ' Time to get out of Dodge!
  100.         IF i > 1 THEN 'check for mixed messages
  101.             IF (lastpd = 0 AND pd > 0) OR (lastpr = 0 AND pr > 0) THEN outStr$ = "Error: digits mixed with letters.": EXIT SUB
  102.         END IF
  103.  
  104.         'save for comparing the next characters
  105.         lastpd = pd: lastpr = pr
  106.     NEXT
  107.  
  108.  
  109.     'OK we have checked that all the characters are either all Roman letters OR all decimal digits.
  110.     ' Time to lay our cards on the table and see which is which from VAL function.
  111.     v = VAL(s$)
  112.  
  113.  
  114.     IF v = 0 THEN ' Then it must be that s$ was all letters that have no value to VAL.
  115.         FOR i = 1 TO 3999 ' So run through the table of Roman strings and match it to what we have in s$.
  116.  
  117.             'Aha a match at i = something, then i is the decimal number for that Roman String.
  118.             'Ship it out in the outStr$ variable, trimmed nice and neat of spaces STR$ tends to add to positive numbers.
  119.             IF R$(i) = s$ THEN outStr$ = _TRIM$(STR$(i)): EXIT SUB
  120.         NEXT
  121.  
  122.         'If we are still in this SUB that means we did not find a matching string, so sorry ;(
  123.         outStr$ = "Error: Invalid Roman Numeral? string."
  124.  
  125.     ELSEIF v > 0 AND v < 4000 THEN ' in range of our array
  126.         'Else s$ has been loaded with digits all this time but are the digits in range of our Roman Numbers?
  127.  
  128.  
  129.         ' Yes it is safe to call on index v of R$(), there will be a Roman Numeral ready to ship out in outStr$,
  130.         ' so put it there.
  131.         outStr$ = R$(v)
  132.  
  133.  
  134.     ELSE
  135.         ' We are not in range, so report a complaint ;(
  136.         outStr$ = "Error: Not in range of 1 to 3999."
  137.     END IF
  138.  
  139.  
  140.  

EDIT: I went over my comments and cleaned up some missing: letters, words, punctuation and thoughts.
EDIT 2: (2020-08-31 12:30PM more changes)
« Last Edit: August 31, 2020, 12:26:53 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Decimal to roman numbers converter
« Reply #27 on: August 31, 2020, 02:18:03 pm »
@Juan Tamarit
Hi Welcome into this explosive forum...
as you can see many members give their apport to the issue with their own experience and knowledge of programming, of BASIC and of  the issue in question....a program can be built in so many ways!

I come back to your first program and here my feedbacks, also if I have seen that you are trying to hang yourself with GOTO and DATA and READ and RESTORE (all good old ways to use stored data into the same EXE)

about
https://www.qb64.org/forum/index.php?topic=2960.msg122151#msg122151

do you want feedback from an user...
1) well done to follow a good teacher in programming
2) wel done to share your thoughts and code here in this forum

3) going to your creature:

 3.1 I find it fine but my first thought is:
     why do you choose an upper limit of 4000 for conversion?
     You can have no limits... see here https://www.math.it/formulario/numeri_romani_convertitore.htm

 3.2 It is fine also the red text presentation... but after some conversion it goes      away above for the scrolling of  output of the program---> I sugget to you to      fix this bug using LOCATE for printing output of conversion or otherwise to re      PRINT the red text presentation before each output before INPUT statement

 3.3 quitting the program using a specific input 0 is an option among so many others
     about the zero into the history see here in      https://es.wikipedia.org/wiki/Cero
Good Luck and
enjoy yourself with programming in QBASIC/QB64
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #28 on: August 31, 2020, 02:32:17 pm »
Hi @Juan Tamarit

RE: your last code post

Are you sure you are a newbie? Really nice extras with cute: opening screen, menus and closing screen; they are colored and sized nicely. But you know that I bet! ;-))

Decimal 2 Roman fine and Roman to Decimal OK for conventional Roman Numerals but I am getting answers for unconventional strings using Roman letters eg:
LLMM = 2050
CCCCM = 1900
LLLC = 150

You could run a reverse check. Check the "Arabic" form reported from SUB Roman 2 Arabic and then run it through
Arabic 2 Roman SUB and see if the 2 strings match.

Very good work, specially from a newbie, you seem to have mastered arrays and SUB / FUNCTIONs.

I look forward to seeing more of your apps.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Decimal to roman numbers converter
« Reply #29 on: August 31, 2020, 03:14:05 pm »
Quote
3.1 I find it fine but my first thought is:
     why do you choose an upper limit of 4000 for conversion?
     You can have no limits... see here https://www.math.it/formulario/numeri_romani_convertitore.htm

Not really, beyond 4000 it gets quite silly stringing MMMMMMMMMMMMMMMMMMMMMMM's until we get to 100's level

Now we could invent along the Roman Pattern:
what for 5,000  maybe F for Five Thousand but we run out of letters (Yikes MF for 4,000?)
what for 10,000, maybe T for Ten Thousand...

probably have enough letters to do a couple of millions. :) Plus too many letters get dangerous as we see with 4000.

Quote
a program can be built in so many ways!
So True! I was hindered in understanding of Juan's code right at the get go, by the way he did DATA and READ it into arrays. Oh, he is setting up for going beyond 1000, aha! There is 0 to 3 levels but the 3rd is incomplete.