Hello everyone.

I have a program that is driving me crazy. It is a cashier change return where the user enter the amount owed and the amount paid and when he/she press calculate the program should display the change due as well as the number of Dollars, Quarters, Dimes, Nickels, and pennies returned to the customer. When I run the program sometimes it gives me the right output and others it gives wrong output and it rounds the output. I just want to let you know that I have the option strict on. I will paste the code below please help me ASAP!!!!!!

Thanks in advance

Option Explicit On
Option Strict On
Option Infer Off

Public Class frmMain

    Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click
        ' close the application
        Me.Close()
    End Sub

    Private Sub btnClr_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClr.Click

        ' clear all the labels and textboxes and prepare the screen for the next entry
        txtOwed.Text = ""
        txtPaid.Text = ""
        lblChangDue.Text = ""
        lblDollars.Text = ""
        lblQuart.Text = ""
        lblDimes.Text = ""
        lblNickels.Text = ""
        lblPenn.Text = ""

        ' send the focus to the Amount owed text box
        txtOwed.Focus()

    End Sub

    Private Sub btnCal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCal.Click


        ' declare named constants
        Const intDOLLARS_VALUE As Integer = 1
        Const decQUART_VALUE As Decimal = 0.25D
        Const decDIMES_VALUE As Decimal = 0.1D
        Const decNICKELS_VALUE As Decimal = 0.05D
        Const decPENN_VALUE As Decimal = 0.01D

        'declare variables
        Dim decOwed As Decimal
        Dim decPaid As Decimal
        Dim decChange As Decimal
        Dim intDollars As Integer
        Dim decRemaining As Decimal
        Dim intQuart As Integer
        Dim decRemainingTwo As Decimal
        Dim intDimes As Integer
        Dim decRemainingThree As Decimal
        Dim intNickels As Integer
        Dim decRemainingFour As Decimal
        Dim intPenn As Integer


        ' calculate the change due
        Decimal.TryParse(txtOwed.Text, decOwed)
        Decimal.TryParse(txtPaid.Text, decPaid)
        decChange = decPaid - decOwed

        ' claculate the dollars
        intDollars = Convert.ToInt32((decChange / intDOLLARS_VALUE) - (decChange Mod intDOLLARS_VALUE))
        decRemaining = decChange - (intDollars * intDOLLARS_VALUE)

        ' calculates the quarters
        intQuart = Convert.ToInt32((decRemaining / decQUART_VALUE) - (decRemaining Mod decQUART_VALUE))
        decRemainingTwo = decRemaining - (intQuart * decQUART_VALUE)

        ' calculate the dimes
        intDimes = Convert.ToInt32((decRemainingTwo / decDIMES_VALUE) - (decRemainingTwo Mod decDIMES_VALUE))
        decRemainingThree = decRemainingTwo - (intDimes * decDIMES_VALUE)

        ' calculate the nickels
        intNickels = Convert.ToInt32((decRemainingThree / decNICKELS_VALUE) - (decRemainingThree Mod decNICKELS_VALUE))
        decRemainingFour = decRemainingThree - (intNickels * decNICKELS_VALUE)

        ' calculate the pennies 
        intPenn = Convert.ToInt32((decRemainingFour / decPENN_VALUE) - (decRemainingFour Mod decPENN_VALUE))

       




        lblChangDue.Text = decChange.ToString("C2")
        lblDollars.Text = Convert.ToString(intDollars)
        lblQuart.Text = Convert.ToString(intQuart)
        lblDimes.Text = Convert.ToString(intDimes)
        lblNickels.Text = Convert.ToString(intNickels)
        lblPenn.Text = Convert.ToString(intPenn)
    End Sub

    Private Sub frmMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ' gets the username

        ' declare a variable
        Dim strUserName As String


        Const strPrompt As String = "Enter username:"
        Const strTITLE As String = "Username Entery"

        ' assign the username to the variable
        strUserName = InputBox(strPrompt, strTITLE)

        ' puts the username beside the Change Calculator
        Me.Text = Me.Text & "  " & strUserName

    End Sub

    Private Sub CLEARLABELS(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles txtOwed.TextChanged, txtPaid.TextChanged

        ' clears all labels when amount owed or amount paid is changed
        lblChangDue.Text = ""
        lblDollars.Text = ""
        lblQuart.Text = ""
        lblDimes.Text = ""
        lblNickels.Text = ""
        lblPenn.Text = ""

    End Sub
End Class

Dani AI

Generated

Brief diagnosis and a safe pattern to follow.

The inconsistent counts come from mixing fractional currency math with rounding-converting routines. Convert.ToInt32 (and VB conversion helpers) will round rather than truncate, and using the floating-division operator (/) together with Mod on non-integer values produces unexpected results when values are very close to a boundary. Also the code calls Decimal.TryParse but ignores its Boolean return value, so invalid input quietly becomes zero. This builds on 's point about rounding and on 's suggestion to work in pennies, while taking 's Decimal advice further: do parsing + rounding to the nearest cent, then do all denomination work in integer cents.

A robust approach (parse, require non-negative change, round to cents, then use integer division and Mod) looks like this:

' parse and validate
Dim owedDec As Decimal
Dim paidDec As Decimal
If Not Decimal.TryParse(txtOwed.Text, owedDec) OrElse Not Decimal.TryParse(txtPaid.Text, paidDec) Then
    lblChangDue.Text = "Invalid input"
    Exit Sub
End If

Dim changeDec As Decimal = paidDec - owedDec
If changeDec < 0D Then
    lblChangDue.Text = "Insufficient payment"
    Exit Sub
End If

' convert to whole cents (round to nearest cent)
Dim totalCents As Integer = Decimal.ToInt32(Decimal.Round(changeDec * 100D, 0, MidpointRounding.AwayFromZero))

Dim dollars As Integer = totalCents \ 100
Dim centsRem As Integer = totalCents Mod 100
Dim quarters As Integer = centsRem \ 25
centsRem = centsRem Mod 25
Dim dimes As Integer = centsRem \ 10
centsRem = centsRem Mod 10
Dim nickels As Integer = centsRem \ 5
Dim pennies As Integer = centsRem Mod 5

' set labels (format changeDec as currency)
lblChangDue.Text = changeDec.ToString("C2")
lblDollars.Text = dollars.ToString()
lblQuart.Text = quarters.ToString()
lblDimes.Text = dimes.ToString()
lblNickels.Text = nickels.ToString()
lblPenn.Text = pennies.ToString()

Notes and caveats: working in integer cents eliminates fractional-cent edge cases and makes denomination math trivial. Using Decimal.Round before converting ensures the correct cent amount (MidpointRounding.AwayFromZero is typically preferred for cashier rounding). Alternatively, if staying with Decimal division, apply Math.Floor when a truncation is intended (as suggested). Always check TryParse results and handle negative or non-numeric input explicitly; keeping Option Strict On is good practice.

Recommended Answers

All 4 Replies

I think there is an easier way to do this. Try instead of using integers, use the decimal data type for ALL of your varibles. It looks like there are situations where your change due got turncated. I.E somewhere in your code a decimal got rounded because it was suppose to be an integer. You know as well as I do, an integer cannot be a real number. I could be wrong.

Your problem is the use of the / operator and your Convert.ToInt32. When the resulting value is a fractional number greater or equal to .5, it rounds up. Put Math.Floor around your divides to stop this, i.e.

intDollars = Convert.ToInt32(Math.Floor(decChange / intDOLLARS_VALUE))

. Saves you all the Mod code, too.

Thank you guys, I appreciate your replies

Regards

I would do everything in pennies. That is, if the input values are (for example) $250 and $127.93, I would convert that to 25000 and 12793 and go from there. That eliminates rounding when you use "\" to extract each denomination.

'provide your own input validation first

Dim cost As Integer = 100 * CDbl(txtCost.Text)
Dim paid As Integer = 100 * CDbl(txtPaid.Text)
.
.
.
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.