Division with decimals below zero vb.net - vb.net

I'm writing a program in vb.net which allows the user to input an amount of money and then outputs the minimum number of coins that are needed to make that amount. For example if the user inputs £3.43 the program would output 1 x £2, 1x £1, 2x £20p, 1x 2p and 1x 1p.
I have the program working for one and two pound coins but as soon as the program checks for smaller coins (E.G. below £1) the program doesn't recognize anything. The program uses division and modulus to do this, for each coin it divides the amount by the value of the coin (ignoring the remainder), sets the value of a variable named "remainder" as the amount modulus by the value of the coin and resets the amount to the value of the remainder
The code is below:
Public Class MinimumCoins
Dim ammount As Decimal
Dim TwoPound As Integer
Dim OnePound As Integer
Dim fifty As Integer
Dim twenty As Integer
Dim ten As Integer
Dim five As Integer
Dim two As Integer
Dim one As Integer
Dim remainder As Decimal
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
ammount = InputBox("Enter Ammount")
TwoPound = ammount \ 2
remainder = ammount Mod 2
ammount = remainder
OnePound = ammount \ 1
remainder = ammount Mod 1
ammount = remainder
remainder = remainder * 100
fifty = ammount \ 50
remainder = ammount Mod 50
ammount = remainder
twenty = ammount \ 20
remainder = ammount Mod 20
ammount = remainder
ten = ammount \ 10
remainder = ammount Mod 10
ammount = remainder
five = ammount \ 5
remainder = ammount Mod 5
ammount = remainder
two = ammount \ 2
remainder = ammount Mod 2
ammount = remainder
one = ammount \ 1
lblOutput.Text = TwoPound & " X" & " £2.00" & vbNewLine & OnePound & " X" & " £1.00" & vbNewLine & fifty & "X" & " 50p" & vbNewLine & twenty & " X" & " 20p" & vbNewLine & ten & " X" & " 10p" & vbNewLine & five & " X" & " 5p" & vbNewLine & two & " X" & " 2p" & vbNewLine & one & " X" & " 1p"
End Sub
End Class
The first two times the program is run (for one pound and two pound coins) it works perfectly fine but then the program displays no coins are needed for any amount smaller than £1.

You set your ammount to the remainder of the Mod 1 (so for an input of 2.53, your ammount is now 0.53)
Then you multiply remainder by 100 and store it back into remainder, so remainder is 53, ammount is still 0.53..
And then you carry on doing maths on the ammount of 0.53, so your program is going to be asking these questions:
"How many times does 50p go into 0.53p?" 0
"How many times does 20p go into 0.53p?" 0
"How many times does 10p go into 0.53p?" 0
And so on..
I haven't given you the exact answer to your problem, but there's enough in here to work it out - it'll be a better learning exercise for you if you think that last part through yourself, rather than me just giving you the answer directly :)
Good luck

Related

Why is (L \ 12) calculating to 0?

I am trying to do calculations through VBA.
I am doing it through the form itself because when Production creates one of these Job Tickets a number of fields can change on the fly. Which Unit of Measure we are running in, which type of Wood, how we Wrap it, etc.
All of these changes affect the total footage or amount of pieces we have to run, which is why I have If-Then-Else statements for them.
It works until I get to Wrap SQ Footage. I get a zero inserted into my field, but when I do the calculations on my own I never get 0.
I created this expression in the control source of one of the Wrap SQ Footages, and it comes out correctly.
=Abs(Int( (([Wrap_Slit1]/12) * [Quantity_Ordered] ) * ( [RIP_Scrap_Rate] + 1))))
Private Sub FTG_Calculations()
'Declare Variable
Dim L As Double
Dim Length As Double
Dim OrderFTG As Double
Dim UoM As String
Dim W As Double
Dim frm As Access.Form
Set frm = Forms!Frm_JobTicket
'Set L equal to Length from Tbl_JobTicketMould
L = DLookup("Length", "Tbl_JobTicketMould", "Access_ID =" & Forms!Frm_JobTicket!Part_Number)
'Convert Length to Feet
Length = (L \ 12)
'Find Unit of Measure for this part
UoM = DLookup("Unit_of_Measure", "Tbl_JobTicketUoM", "Access_ID =" & Forms!Frm_JobTicket!Part_Number)
'Mupltiply Length times Quantity to get Order Footage
OrderFTG = Int((Length * Me.Txt_Pcs_JobTicket))
'If UoM is PCS then insert that number. Otherwise set equal to Quantity Ordered divided by Length of piece(in FT)
If UoM = "PCS" Then Me.Txt_Pcs_JobTicket = Me.Quantity_Ordered Else: Me.Txt_Pcs_JobTicket = Abs(Int(Me.Quantity_Ordered \ Length))
'Define limits of the loop. Then runs through all Wrap SQ FTG fields and inputs calculation
For W = 1 To 3
'If UoM is PCS then calculate Order Footage to find Wrap Sqaure Footage. Otherwise take slit size in FT and multiply by Order Quantity and Scrap Rate
If UoM = "PCS" Then
frm("Txt_Wrap" & W & "SQFTG_JobTicket") = (((frm("Wrap_Slit" & W) \ 12) * OrderFTG) * (Round((frm("RIP_Scrap_Rate")), 3) + 1))
Else: frm("Txt_Wrap" & W & "SQFTG_JobTicket") = (((frm("Wrap_Slit" & W) \ 12) * frm(Quantity_Ordered)) * (frm(RIP_Scrap_Rate + 1)))
End If
Next W
I figured out the issue is in the (frm("Wrap_Slit" & W) \ 12) area. Wrap_Slit1 shows a value of 2 in the data tips, but when I divide by 12 it comes out to 0.
All of my data points are set to double, and the variables are declared as double. It is rounding down when it should come out to .16667.
Place the following code before the:
If UoM = "PCS" Then
Msgbox code:
MsgBox("Current State:" & vbCrLf & _
"UoM:" & vbTab & UoM & vbCrlf & _
"OrderFTGL" & vbTab & OrderFTG & _
"Wrap_Slit1:" & vbTab & Me.Wrap_Slit1 & _
... continue pattern for other desired values in calculation...
"Continue...", vbOK)

Showing the name of the most expensive product in vb

i'm pretty new to programming and i got stuck trying to write a program where you type in the name and prices of products and you get back the total, the name+ prices and the most expensive product. Everything works fine except showing the name of the most expensive product.
Here's what i've done
""
Public Class Mrj
Shared Sub main()
Dim i, n As Integer
Console.WriteLine("Enter the number of products")
n = Console.ReadLine()
Dim Products_name(n) As String
Dim Products_price(n), HT, TTC, TVA, max As Decimal
For i = 1 To n
Console.WriteLine("Enter the name of the product " & i)
Products_name(i - 1) = Console.ReadLine()
Console.WriteLine("Enter the price of the product " & i)
Products_price(i - 1) = Console.ReadLine()
HT = HT + Products_price(i - 1)
Next
For i = 1 To n
Console.WriteLine(Products_name(i - 1) & " " & Products_price(i - 1))
Next
TVA = 0.2 * HT
TTC = HT + TVA
Console.WriteLine("Total to pay " & TTC)
max = Products_price(0)
For i = 1 To n - 1
If max > Products_price(i) Then
Else
max = Products_price(i)
End If
Next
Console.WriteLine("The product the most expensive is" & max & Products_name(i))
End Sub
End Class
""
I think the problem is that you are using i to get the name of the most expensive product, but that index i is always i = n since you don't save the index of the maximum value.
You should add a new variable where you store the index everytime you get a new maximum value, and use it in the last line.
Your for loop should be something like this:
Dim max_index As Integer
For i = 1 To n - 1
If max > Products_price(i) Then
Else
max = Products_price(i)
max_index = i
End If
Next
Console.WriteLine("The product the most expensive is" & max & Products_name(max_index))
Try this out and check if it works.
Turn on Option Strict now and forever. Project Properties -> Compile tab. Also for future projects Tools -> Options -> Projects and Solutions -> VB Defaults
You cannot assume that a user will actually enter a number. Test with TryParse.
Arrays in vb.net are declared Products_name(upper bound). In this case that would be Products_name(n-1)
Instead of doing i - 1 for the indexes in the For loop, start our with For i = 0 to n-1
I decided to not use the parallel arrays. Instead I made a tiny class and declared a List(Of Product). I filled the list with the user input setting the Properties of the Product.
I used Linq instead of loops for sums and max. Not necessarily faster but can be accomplished in a single line of code.
I use interpolated strings to display results. When your string is preceded by a $, you can insert variables directly in the text surrounded by braces. The colon following Price indicates a formatting character. Here, I used a C for currency.
Public Class Product
Public Property Name As String
Public Property Price As Decimal
End Class
Sub main()
Dim ProductList As New List(Of Product)
Dim n As Integer
Console.WriteLine("Enter the number of products")
Integer.TryParse(Console.ReadLine, n)
For i = 1 To n
Dim p As New Product
Dim pr As Decimal
Console.WriteLine("Enter the name of the product " & i)
p.Name = Console.ReadLine()
Console.WriteLine("Enter the price of the product " & i)
Decimal.TryParse(Console.ReadLine, pr)
p.Price = pr
ProductList.Add(p)
Next
For Each p In ProductList
Console.WriteLine($"{p.Name} {p.Price:C}")
Next
Dim SubTotal As Decimal = ProductList.Sum(Function(item) item.Price)
Dim Tax As Decimal = 0.2D * SubTotal
Dim Total = SubTotal + Tax
Console.WriteLine($"Total to pay {Total:C}")
Dim Prod = ProductList.OrderByDescending(Function(p) p.Price).FirstOrDefault()
Console.WriteLine($"The product the most expensive is {Prod.Name} at {Prod.Price:C}")
Console.ReadKey()
End Sub

VB InputBox Validation Inquiry

I know InputBox isn't the best for validation, but that was one of the specifications on the program I am writing for class. My problem is that despite the if or case statements I make to validate the data entered, it still accepts the data while simultaneously displaying the MsgBox's I have in my code..
Essentially what I would like the case statement to do is to properly filter the data that is entered and not proceed onto the next floor if the data is invalid and request that new data be entered. If the data is valid, proceed onto the next floor.
Const ROOMS As Integer = 30
Const MAX_FLOOR As Integer = 16
Dim floor As Integer
Dim StrOccupancy As String
Dim occupancy As Integer
Dim occupancyRate As Double
Dim occupancySum As Integer
Dim overallRate As Double
lblOccupancyRate.Text = String.Empty
lblRoomsOccupied.Text = String.Empty
output.Items.Clear()
For floor = 1 To MAX_FLOOR
If floor = 13 Then
Continue For
End If
StrOccupancy = Integer.TryParse(InputBox("Enter the number of rooms occupied for floor:" & Space(1) & floor), occupancy)
Select Case occupancy
Case < 1
MsgBox("Please enter a number of 1 or more occupants.")
Case > 30
MsgBox("Amount of occupants must be between 1-30.")
Case >= 1 And occupancy <= 30
occupancyRate = (occupancy / ROOMS)
occupancySum += occupancy
overallRate = occupancySum / (ROOMS * 15)
End Select
output.Items.Add("Floor: " & floor & " Rooms Occupied: " & occupancy _
& " Occupancy Rate: " & occupancyRate.ToString("P2"))
lblRoomsOccupied.Text = occupancySum.ToString
lblOccupancyRate.Text = overallRate.ToString("P2")
Next
output.Items.Add("")
output.Items.Add("Total occupancy is" & Space(1) & occupancySum & Space(1) & "and" & Space(1) & overallRate.ToString("P2") & Space(1) & " of rooms are full.")
End Sub
Had a little time to check your code and actually you need a Boolean that validates if the occupancy requirements are met and loop if not. The code would be something like this:
For floor = 1 To MAX_FLOOR
'Boolean to validate the occupancy meet the requirements
Dim goodOccupancy As Boolean = False
'Do loop enters at least 1 time and runs the code inside it
Do
Integer.TryParse(InputBox("Enter the number of rooms occupied for floor:" & Space(1) & floor), occupancy)
Select Case occupancy
Case < 1
MsgBox("Please enter a number of 1 or more occupants.")
Case > 30
MsgBox("Amount of occupants must be between 1-30.")
Case >= 1 And occupancy <= 30
occupancyRate = (occupancy / ROOMS)
occupancySum += occupancy
overallRate = occupancySum / (ROOMS * 15)
'If the requirements are met we change the Boolean value to continue with the execution
goodOccupancy = True
End Select
'We loop if the requirements are not met
Loop Until goodOccupancy = True
output.Items.Add("Floor: " & floor & " Rooms Occupied: " & occupancy _
& " Occupancy Rate: " & occupancyRate.ToString("P2"))
lblRoomsOccupied.Text = occupancySum.ToString
lblOccupancyRate.Text = overallRate.ToString("P2")
Next
But please next time try to be more explicit with your code. Most of people won't check what is going on. Do not expect people to solve your problems without guidance. Please read the How to ask guide it will give you a light to use the site as it is supposed to be used

Division arithmetic in VB.net automatically rounding off

I have a bit of an issue with the following piece of code.
Dim k As Integer
k = (TextBox1.Text - 750) \ 250
MsgBox("There should be " & k & " items")
Lets say that textbox1 has a value of 3050 the outcome would be 9.20 however my Mesagebox returns 9 which is not what I want. In fact, I want to see it without the rounding off
How do I do that?
\ is integer division in VB, so you need to use / instead.
See here (MSDN Documentation) for more information on VB operators.
Also, as is mentioned in the comments, you're storing k as an integer - use double (or whatever) instead.
So, how about:
Dim k As Double
Dim tbText as Double
If Double.TryParse(TextBox1.Text, tbText) Then
k = (tbText - 750) / 250
MsgBox("There should be " & k & " items")
End If
If you're certain that TextBox1.Text will be a number, you don't have to use TryParseit like I did - but I don't think you should ever trust a user to get it right...

Need help displaying output for Golf Game

I need some help, I don't know how I would display the players and the hole that they won in this program.
Public Class GolfGame
Private Sub btnPlay_Click(sender As Object, e As EventArgs) Handles btnPlay.Click
Dim array(3, 8) As Integer
Dim intLow As Integer = 0
Scores.Items.Add(vbTab & "Hole 1" & vbTab & "Hole 2" & vbTab & "Hole 3" & vbTab & "Hole 4" & vbTab & "Hole 5" & vbTab & "Hole 6" & vbTab & "Hole 7" & vbTab & "Hole 8" & vbTab & "Hole 9")
Randomize()
For outer = 0 To 3
For inner As Integer = 0 To 8
array(outer, inner) = Int((8 * Rnd()) + 1)
Next
Scores.Items.Add("Player " & outer + 1 & vbTab & array(outer, 0) & vbTab & array(outer, 1) & vbTab & array(outer, 2) & vbTab & array(outer, 3) & vbTab & array(outer, 4) & vbTab & array(outer, 5) & vbTab & array(outer, 6) & vbTab & array(outer, 7) & vbTab & array(outer, 8))
Next
For i As Integer = 0 To 8
For j As Integer = 0 To 3
If array(j, i) < intLow Then
intLow = array(j, i)
If j = 0 And i = 0 Then
P1.Text = "Player 1 has won this hole."
ElseIf j = 1 And i = 0 Then
P2.Text = "Player 2 has won this hole."
ElseIf j = 2 And i = 0 Then
P3.Text = "Player 3 has won this hole"
ElseIf j = 3 And i = 0 Then
P4.Text = "Player 4 has won this hole."
End If
End If
Next
intLow = 9
Next
End Sub
End Class
The If statement does not seem to be working within the loop. Any ideas to tackle this? Should the output just be one big if statement, or is there something simpler that I am just missing?
It looks like you're just learning, so I'll try to help you out.
First of all, you don't say how Scores and P1 through P4 are defined. It looks like Scores might be a List(Of String) and P1 through P4 are text boxes or labels of some sort. I'll make those assumptions for now. You begin by sending output to Scores, but then you use the text boxes instead. You need to settle on how you're going to display your output and go with one option.
You begin by assigning a random integer from 1 to 8 for each player/hole combination. That part looks OK.
Then you've attempted to write an algorithm to determine which player won each hole. What you've written is very confused and won't work. There are multiple problems.
intLow is 0 when you attempt to find the winner of the first hole. Then you set it to 9 for holes 2 through 9 (outer 1 through 8). That can't work. You need to be consistent.
When intLow is 0, your main If statement:
If array(j, i) < intLow Then
...will always fail, because the values you've stored in Scores will never be less than zero.
On subsequent iterations, your main If statement will always succeed because intLow has been set to 9 and the maximum score is 8. However, by this time, i will not be 0 and all your inner If statements will fail.
intLow contains the wrong information. You want to store the player who won the hole, not what the low score was. If intLow contains the index of the player who won the hole, then you can easily get the score.
So your program essentially does nothing. You need to adjust the algorithm to properly determine which player won a hole. This would do it:
For i As Integer = 0 To 8
intLow = 0
For j As Integer = 1 To 3
If array(j, i) < array(intLow, i) Then
intLow = j
End If
Next j
' At this point, you know that player intLow+1 won hole i+1 with a score of
' array(intLow, i). Ties always go to the first player who made that score.
Next i
In this revision, notice that we compare players to one another rather than to a constant value like 9. When determining the minimum or maximum in a list, this is a better practice. Granted, the scoring range for a hole of golf is always 1 - 8, but most minimums and maximums tend to have a way of changing over time. You want your algorithm to work no matter what.
I'll leave the output part up to you. This looks like an assignment and I've probably given too much away already.
Other suggestions:
Scores is a poorly named variable. It contains output, so Output might be a better name.
array is not descriptive. It contains scores. Once Scores is renamed, a good name for array would be Scores.
i could be called hole and j could be called player. That would help you keep things straight.
intLow could be called winner, which implies that the variable contains the index of the winner. intLow could mean low score or player with the lowest score. This ambiguity might have confused you. It definitely confused me.
There are native .Net methods for truncating the decimal portion of a number and for generating random numbers. There are even ways to generate random integers directly. You are using a legacy way of doing it, which VB.net provides for backward compatibility with VB6. That's 1990s technology. Programmers unfamiliar with VB6 will look at your code will find this very confusing, which is why it's generally better to use the native features of the .Net framework.