Results 1 to 31 of 31

Thread: Roman Numeral Calculator

Threaded View

  1. #23
    PowerPoster
    Join Date
    Nov 2002
    Location
    Manila
    Posts
    7,629

    Re: Roman Numeral Calculator

    Quote Originally Posted by xtishx
    But I'm having problems trying to write the validation rules for:

    • making sure the numeral that is entered is in the correct order
    • the additive rule (explained above)
    My previous post was hasty so...

    As with any string manipulation routine, you will have to prepare your string to facilitate manipulation, eg. no spaces, UCase(), and so on. Use the validate event of the textbox. I used only one textbox in my tests.

    You will then have to parse the roman expression and place it in a structure to facilitate iteration through the operands and operators. I found inserting vbCrLf works.
    VB Code:
    1. Public Sub ExpressionToArray(ByVal Expression As String, RetArray() As String) As Long
    2.    ExpressionToArray = -1  'init value
    3.  
    4.    'It is assumed that spaces have already been eliminated
    5.    Expression = Replace(Expression, "+", vbCrLf & "+" & vbCrLf)
    6.    Expression = Replace(Expression, "-", vbCrLf & "-" & vbCrLf)
    7.    Expression = Replace(Expression, "*", vbCrLf & "*" & vbCrLf)
    8.    Expression = Replace(Expression, "/", vbCrLf & "/" & vbCrLf)
    9.  
    10.    'You can insert a check here
    11.    'If there is a leading or trailing vbCrLf, or there are two consecutive vbCrLf's
    12.    '   in the expression then you are lacking operands or have to many operators
    13.  
    14.    RetArray = Split(Expression, vbCrLf)
    15.    ExpressionToArray = 0
    16. End Sub
    17.  
    18. 'You can then iterate on the returned array, eg:
    19. '
    20. 'Dim sArray() As String
    21. '
    22. '   Call ExpressionToArray(txtInput.Text, sArray)
    23. '   For x=0 To Ubound(sArray)
    24. '      Select Case sArray(x)
    25. '      Case "+", "-", "*", "/"
    26. '         'do nothing, skip operators
    27. '      Case Else
    28. '         Call RomanToDecimal(sArray(x))  'pass the roman operand and update array value
    29. '      End Select
    30. '   Next
    31. '
    32. '   txtOutput.Text = EvaluateExpression(Join(sArray, ""))

    You can then do 3 levels of validation on each roman operand:
    - An initial check to screen out invalid characters (A, B, E...) and the more obvious errors such as IL or VV. This can easily be accomplished with InStr() > 0

    - Validity checks during the conversion into an expression based on places (thousands, hundreds, tens, and ones as mentioned in Rhino's link).

    - Rechecking the expression to make sure that the values progress from thousands place to ones correctly as I explained in an earlier post.

    Conversion based on digit place is a lot easier than nested conditional statements to process the string from left to right. You will also need a sub to count the number of instances of your roman character.

    VB Code:
    1. Public Function CharCount(RomanChar As String, Expression As String) As Long
    2. Dim sTemp As String
    3.  
    4.    sTemp = Replace(Expression, RomanChar, "")
    5.    CharCount = (Len(Expression) - Len(sTemp)) / Len(RomanChar)
    6. End Function
    7.  
    8. Public Function RomanToDecimal(ByRef RomanNum As String) As Long
    9. 'note that I passed by reference so I can update the value of RomanNum in the called procedure
    10.  
    11.    RomanToDecimal = -1
    12.  
    13.    If SimpleCheck(RomanNum)  <> ) Then error occured 'check for common errors and invalid letters
    14.    If ReplaceOnes(RomanNum) <> 0 Then error occured
    15.    If ReplaceTens(RomanNum) <> 0 Then error occured
    16.    If ReplaceHundreds(RomanNum) <> 0 Then error occured
    17.    If ReplaceThousands(RomanNum) <> 0 Then error occured
    18.    'you will need to correct the leading + sign in the final expression
    19.  
    20.    If PlacesCheck(RomanNum) <> 0 Then error occured
    21.    'You will reuse ExpressionToArray() in placescheck() to
    22.    'get an array to check by iteration to ensure that
    23.    'the decimal values progress in order from thousands to ones
    24.  
    25.    romanNum = EvaluateExpression(RomanNum) & ""
    26.  
    27.    RomanToDecimal = 0  'completed successfully
    28. End Function
    29.  
    30.  
    31. 'Pseudocode for ones place, do the same for the other places
    32. ' note validity checks during conversion
    33. Public Function ReplaceOnes(ByRef Expression As String) As Long
    34. Dim IVcount As Long
    35. Dim IXcount As Long
    36.  
    37.    ReplaceOnes = -1
    38.    IVcount = CharCount("IV", Expression)
    39.    IXcount = CharCount("IX", Expression)
    40.  
    41.    If IVcount > 0 and IXcount > 0 Then
    42.       'error, IX and IV cannot exist at the same time    
    43.    ElseIf IVcount > 1 Then
    44.       'error, only one IV in a number
    45.    ElseIf IXcount > 1
    46.       'error only one instance of IX is valid
    47.    ElseIf IVcount = 1  
    48.       'notice no need to check IXcount = 0,
    49.       'it is implied cause first case already handles IVcount > 0 and IXcount > 0
    50.       Expression = Replace(Expression, "IV", "+4")
    51.       If CharCount("I", Expression) > 0 Or CharCount("V", Expression) > 0 Then
    52.          'error, I's or V exist when IV already used
    53.       End If
    54.    ElseIf IXcount = 1
    55.       'almost same format as IVcount = 1, test I's and X
    56.    ElseIf IVcount = 0 and IXcount = 0
    57.       If CharCount("V", Expression) > 1 Then
    58.          'error, only one V is valid
    59.       Else
    60.          Expression = Replace(Expression, "V", "+5")
    61.       End If
    62.  
    63.       If CharCount("I", Expression) > 3 Then
    64.          'error, only up to 3 I's valid
    65.       Else
    66.          Expression = Replace(Expression, "I", "+1")
    67.       End If
    68.    End If
    69.  
    70.    ReplaceOnes = 0 'completed with no errors
    71. End Sub
    72.  
    73. Public Function EvaluateExporession()
    74. Dim oSCRCNT As New ScriptControl
    75.  
    76.    'sorry have to go... but this will have only about 3 to 5 lines
    77.    'anyone for the save??
    78. End Function

    And I mentioned the script control and the eval method. Thread starter, this is what you will use to perform arithmetic operations on your roman numerals.

    You enter an expression: "X + VII"
    You get an expression array and call romantodecimal:
    Array("10","+","5 + 1 + 1") --> Array("10","+", "7") after romantodecimal call
    RomanToDecimal also performs the Eval method of the script control to get the result of 5+1+1 = 7
    You then perform another Eval on the final expression "10+7"

    You will need to set the project reference of the script control
    You will need to create a new instance of the object in EvaluateExpression()
    you will need to set the lagnuage property of the object to "vbscript"
    Then finally call the Eval method and get the result of your arithmetic expression.
    Last edited by leinad31; Mar 25th, 2006 at 02:37 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width