losing precision while calculating cost - vb.net

I've got this program to calculate the cost of sheets of paper. First the prices and bundles are declared and intialized. Then I use if else statements with division and modulos to break down the bundle into charging rates. Although my paper bundle amounts are correctly computed, my total costs are off. Can anyone spot what I'm doing wrong here?
Module Paper
Sub Main()
'declare variables
Dim PaperAmountReq As Double
Dim PricePer_1_Sheet As Double = 0.1
Dim PricePer_100_Sheets As Double = 0.055
Dim PricePer_500_Sheets As Double = 0.04
Dim PricePer_1000_Sheets As Double = 0.03
Dim NumberOfSingles As Double = 0
Dim NumberOf100s As Double = 0
Dim NumberOf500s As Double = 0
Dim Numberof1000s As Double = 0
Dim TotalCost As Double
Console.Write("Enter number of sheets of paper needed: ")
PaperAmountReq = Console.Readline
If PaperAmountReq / 1000 >= 1 Then
Numberof1000s = PaperAmountReq \ 1000
PaperAmountReq = PaperAmountReq Mod 1000
End If
If PaperAmountReq / 500 >= 1 Then
NumberOf500s = PaperAmountReq \ 500
PaperAmountReq = PaperAmountReq Mod 500
End If
If PaperAmountReq / 100 >= 1 Then
Numberof100s = PaperAmountReq \ 100
PaperAmountReq = PaperAmountReq Mod 100
End If
If PaperAmountReq / 1 = PaperAmountReq Then
NumberOfSingles = PaperAmountReq
End If
'TotalCost = (Convert.ToDouble(Numberof1000s) * PricePer_1000_Sheets) + (Convert.ToDouble(NumberOf500s) * PricePer_500_Sheets) + (Convert.ToDouble(Numberof100s) * PricePer_100_Sheets) + (Convert.ToDouble(NumberOfSingles) * PricePer_1_Sheet)
TotalCost = (Numberof1000s * PricePer_1000_Sheets) + (NumberOf500s * PricePer_500_Sheets) + (Numberof100s * PricePer_100_Sheets) + (NumberOfSingles * PricePer_1_Sheet)
Console.WriteLine("Number of 1000 packages: " & Numberof1000s)
Console.WriteLine("Number of 500 packages: " & Numberof500s)
Console.WriteLine("Number of 100 packages: " & Numberof100s)
Console.WriteLine("Number of singles packages: " & NumberOfSingles)
Console.Write("Total Cost: " & TotalCost)
End Sub
End Module

With this:
If PaperAmountReq / 1000 >= 1 Then
Numberof1000s = PaperAmountReq \ 1000
PaperAmountReq = PaperAmountReq Mod 1000
End If
if you have 1500, you are setting Numberof1000s equal to 1 - not 1000. So when you calculate your total cost, your value of (presumably) cost/sheet is being multiplied by 1 instead of 1000.
Either change your equation here
TotalCost = (Numberof1000s * PricePer_1000_Sheets) + (NumberOf500s * PricePer_500_Sheets) + (Numberof100s * PricePer_100_Sheets) + (NumberOfSingles * PricePer_1_Sheet)
to be something like
TotalCost = (Numberof1000s * PricePer_1000_Sheets * 1000) + (NumberOf500s * PricePer_500_Sheets * 500) + (Numberof100s * PricePer_100_Sheets * 100) + (NumberOfSingles * PricePer_1_Sheet * 1)
or adjust the PricePer_XXX_Sheets values to be the equivalent values.
Dim PricePer_1_Sheet As Double = 0.1
Dim PricePer_100_Sheets As Double = 0.055 * 100
Dim PricePer_500_Sheets As Double = 0.04 * 500
Dim PricePer_1000_Sheets As Double = 0.03 * 1000

Well your numberof variables should be integers or maybe bigintegers if not big enough as should PaperAmountReq
Your code seems to be assuming integer division
in these segments
If PaperAmountReq / 500 >= 1 Then
NumberOf500s = PaperAmountReq \ 500
PaperAmountReq = PaperAmountReq Mod 500
End if
in actual fact because you are using doubles, it's doing floating point division.
I'd also recommend that you use decimal instead of double for your price? and Total Cost variables.
Doubles are very precise, but often very inaccurate.

Looks like you need to convert the NumberOfXXXs variables to sheets, rather than bundles.
Your formula at the end uses per-sheet costs with per-bundle numbers. Either update the costs to be per-bundle, or update the bundle numbers to equal the round number of sheets in that bundle:
TotalCost = NumberOf1000s * 1000 * PricePer_1000_Sheets

Dim PricePer_100_Sheets As Double = 0.055
Dim PricePer_500_Sheets As Double = 0.04
Dim PricePer_1000_Sheets As Double = 0.03
should be
Dim PricePer_100_Sheets As Double = 0.055 * 100
Dim PricePer_500_Sheets As Double = 0.04 * 500
Dim PricePer_1000_Sheets As Double = 0.03 * 1000

Related

Using VBA to iteratively solve a system of equations

I'm trying to solve the following system of equations in VBA:
I have looked for other similar questions and I can't find any with suitable solutions. I have already solved the equations in a worksheet by simply entering the equations as formulae is separate cells (which will initially create a circular reference warning) and the enabling iterative calculation) - given that I know DR will always be greater than PR, I thought an iterative approach of incrementally reducing PR from an initial value of DR would work in VBA. For reference, the worksheet used is shown below:
The formula in G9 is =(G8*B6)/(G10+273.15), i.e. equation 2 (see above), and the formula in G10 is =(B6+(B6*(-1+((G9*(B3-B35))/(B3-B35))^0.263)/B34))-B33*(B6+(B6*(-1+((G9*(B3-B35))/(B3-B35))^0.263)/B34)), i.e. equation 1 (see above).
When I try to do this programmatically in VBA by reducing PR incrementally from an initial value of DR, it doesn't work. My code is below:
Sub ChargeTempAndPressureCalculations()
Dim AP_hPa As Double
Dim AP_psi As Double
Dim TIn_C As Double
Dim TIn_K As Double
Dim PR As Double
Dim Ei As Double
Dim Et As Double
Dim Vci As Double
Dim DR As Double
Dim TOut_C As Double
AP_hPa = 1029 'Input
AP_psi = AP_hPa * 100 * 0.000145038
TIn_C = 15 'Input
TIn_K = TIn_C + 273.15
Et = 0.75 'Input
Ei = 0.75 'Input
Vci = 0.5 'Input
DR = 2.7103502887329 'Input
PR = DR
Do Until TOut_C = (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et)) - Ei * (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et)) And PR = (DR * TIn_K) / (TOut_C + 273)
PR = PR - 0.00000000001
Loop
Debug.Print "Charge air temperature = " & TOut_C
Debug.Print "Pressure Ratio = " & PR
End Sub
It's clearly the loop that's the issue but what is it that I'm doing wrong?
Edit:
I've split equation 1 to prevent the 'Equation too complex' error observed by another user, mentioned in the comments. I've also added a control to prevent the number of steps going above 1000.
Sub ChargeTempAndPressureCalculations()
Dim AP_hPa As Double
Dim AP_psi As Double
Dim TIn_C As Double
Dim TIn_K As Double
Dim PR As Double
Dim Ei As Double
Dim Et As Double
Dim Vci As Double
Dim DR As Double
Dim TOut_C As Double
Dim A As Double
Dim B As Double
Dim i As Integer
AP_hPa = 1029 'Input
AP_psi = AP_hPa * 100 * 0.000145038
TIn_C = 15 'Input
TIn_K = TIn_C + 273.15
Et = 0.75 'Input
Ei = 0.75 'Input
Vci = 0.5 'Input
DR = 2.7103502887329 'Input
PR = DR
Do Until i > 1000 Or (TOut_C = A - Ei * B And PR = (DR * TIn_K) / (TOut_C + 273))
'Spliting equation for TOut_C to simplify the expression and prevent an error
A = (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et))
B = (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et))
PR = PR - 0.00000000001
i = i + 1
Loop
Debug.Print "Charge air temperature = " & TOut_C
Debug.Print "Pressure Ratio = " & PR
End Sub
Having read the answer provided, I'm still none the wiser as to how to resolve my issue.
I've gone over your calculation a bit more and I presume you want to stop if the increment of PR and TOut_C is very marginal...
The below code does exactly that. It calculates TOut_C at a given PR, it subsequently calculates the PR corresponding to that TOut_C, the loop then substitutes the newly calculated PR into the TOut_C calculation and so on.
It calculates the difference between the substitute calculation and the previous calculation and if there is no longer a 'large' offset between the two it stops the loop.
Sub ChargeTempAndPressureCalculations()
Dim AP_hPa As Double
Dim AP_psi As Double
Dim TIn_C As Double
Dim TIn_K As Double
Dim PR As Double
Dim Ei As Double
Dim Et As Double
Dim Vci As Double
Dim DR As Double
Dim TOut_C As Double
AP_hPa = 1029 'Input
AP_psi = AP_hPa * 100 * 0.000145038
TIn_C = 15 'Input
TIn_K = TIn_C + 273.15
Et = 0.75 'Input
Ei = 0.75 'Input
Vci = 0.5 'Input
DR = 2.7103502887329 'Input
PR = DR
dTOut_C = 1 'Set to arbitrary number to initialize the loop
dPR = 1 'Set to arbitrary number to initialize the loop
Do Until dPR < 0.0000000001 And dTOut_C < 0.0000000001
'Calculate the TOut_C and PR
TOut_C = (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et)) - Ei * (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et))
PR = (DR * TIn_K) / (TOut_C + 273)
'Calculate difference relative to last calculation
dPR = PR - PR0
dTOut_C = TOut_C - TOut_C0
'Set the last calculation as previous calculation and re-do loop
PR0 = PR
TOut_C0 = TOut_C
Loop
Debug.Print "Charge air temperature = " & TOut_C
Debug.Print "Pressure Ratio = " & PR
End Sub
Given your initial input the output is:
Charge air temperature = 93.2076926574912
Pressure Ratio = 2.13263525413933
Was that what you were looking for ?
PS: Technically what you should do is mathematically rewrite the equation to solve for PR based on DR as that is in essence what you are doing...
Note that in:
Do Until TOut_C = ...
the = sign is a comparisson and not an assignment. As TOut_C has not been used yet, it is set to zero by VB and so you are comparing whether the right hand side is zero. This does not seem to be your intention, as you use TOut_C in the AND part as TOut_C + 273 which then would always be 273.
But if you want to compare with zero, then note that the RHS will probably never become zero in floating point arithmetic and you must compare with an "epsilon", a small value that is your precission threshold. For example:
Private Const eps = 0.00000000001 ' must be smaller than your step size
Do Until Abs(TOut_C - RHS) < eps
I leave fixing this to you. (I also get an error "Expression too complex" on my Excel version.)
There is primarily two problems...
In your Do..Loop you want the code to break on TOut_C = <something based on PR> AND PR = <something based on TOut_C>
Both equation however lead to a double datatype, this is almost imposibble to have that be an = comparison as the likelyhood of hitting that equal point are virtualy zero (as I explained here)
So, you would want to set a more flexible parameter such as TOut_C > 63 for example.
The second thing that I can find is that the equations are just that, equations. So they'll produce a number but as that number is the result of the equation, but what would define the endpoint ? TOut_C is never defined and subsequently compared as indicated, your code starts with PR being 2.71... but Tout_C is 0.
So could you elaborate more on the correlation between TOut_C and PR and what would be the solution values for either or both of them ? Or are you trying to solve a balance point i.e. for a which TOut_C do both functions achieve the same result ? (That would require mathematically re-writing either function to express the same output) So rewrite the function for PR to produce Tout_C...
The loop works (i.e. it loops) if you write it like so...
It doesn't solve it, but at least you know it loops...
Do Until TOut_C = 15 And PR = 22
TOut_C = (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et)) - Ei * (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et))
PR = (DR * TIn_K) / (TOut_C + 273)
PR = PR - 0.00000000001
Loop
See http://www.decisionmodels.com/calcsecretsc.htm on how Excel processes circular references. Basically, it just calculates each cell, ignoring the circular reference and then it updates the values in each iteration.
Applying this to your VBA routine produces the following sub routine:
Sub ChargeTempAndPressureCalculations()
' input variables
Dim AP_hPa As Double
Dim AP_psi As Double
Dim TIn_C As Double
Dim TIn_K As Double
Dim Ei As Double
Dim Et As Double
Dim Vci As Double
Dim DR As Double
' temporary variables
Dim Td As Double
Dim Pd As Double
Dim A As Double
' output variables
Dim TOut_C As Double
Dim PR As Double
' iteration control
Dim eps As Double
Dim i As Integer
AP_hPa = 1029
AP_psi = AP_hPa * 100 * 0.000145038
TIn_C = 15
TIn_K = TIn_C + 273.15
Et = 0.75
Ei = 0.75
Vci = 0.5
DR = 2.7103502887329
PR = DR
eps = 0.00000000001
i = 0
Do
Td = TOut_C ' remember values from previous iteration ( 'd' means 'delta')
Pd = PR
A = (TIn_K + (TIn_K * (-1 + ((PR * (AP_psi - Vci)) / (AP_psi - Vci)) ^ 0.263) / Et))
TOut_C = A - Ei * A
PR = (DR * TIn_K) / (TOut_C + 273)
i = i + 1
Debug.Print TOut_C & ", " & PR & "(" & Abs(Td - TOut_C) & ", " & Abs(Pd - PR) & ")" ' show progression
' loop until the difference is less than eps or max iterations reached
Loop While (i < 100 And (Abs(Td - TOut_C) > eps And Abs(Pd - PR) > eps))
Debug.Print "Charge air temperature = " & TOut_C
Debug.Print "Pressure Ratio = " & PR
Debug.Print "number of iterations: " & i
End Sub
Output:
100.835921416446, 2.08911822261291(100.835921416446, 0.621232066119993)
92.5738330344343, 2.13633297880164(8.26208838201211, 4.72147561887288E-02)
93.2611120407512, 2.13232420812257(0.687279006316899, 4.00877067907057E-03)
93.2031960023579, 2.13266144103602(5.79160383933299E-02, 3.37232913455665E-04)
93.2080712078647, 2.13263304962791(4.87520550686327E-03, 2.83914081067316E-05)
93.2076607895546, 2.13263543972443(4.10418310181626E-04, 2.39009651137323E-06)
93.2076953402811, 2.13263523851592(3.45507265677725E-05, 2.01208508077144E-07)
93.2076924316548, 2.1326352554545(2.90862628560262E-06, 1.6938581648418E-08)
93.2076926765153, 2.13263525402854(2.44860444809092E-07, 1.42596112695514E-09)
93.2076926559019, 2.13263525414858(2.06133563551703E-08, 1.200430865822E-10)
93.2076926576372, 2.13263525413848(1.73530168012803E-09, 1.01052499701382E-11)
93.2076926574912, 2.13263525413933(1.46073375617561E-10, 8.5043083686287E-13)
Charge air temperature = 93.2076926574912
Pressure Ratio = 2.13263525413933
number of iterations: 12

VB program to calculate monthly deposits plus interest

I am having issues trying to make a calculator that accurately calculates deposits plus the amount of interest that is added monthly. I dont know how to incorporate a loop that can add monthly deposits to total deposits, then adds the total deposits plus total interest times the interest rate / 100 / 12 to the total deposits. Here is what I have so far. Sorry am super new to VB !
Dim intMonthlyDeposit As Interger
Dim intMonthsTotal As Integer
Dim intAnnualRate As Interget
Dim decTotalDeposits As Decimal
Dim decTotalInterest As Decimal
Dim decTotalTotal As Decimal
Try
intMonthlyDeposit = CInt(txtMonthlyDeposits.Text)
intMonthsTotal = CInt(txtMonths.Text)
decAnnualRate = CDec(txtAnnualRate.Text)
decTotalDeposits = 0
decTotalInterest = 0
decTotalTotal = 0
decTotalDeposits = decMonthlyDeposit * intMonthsTotal
decTotalInterest = decTotalDeposits * (decAnnualRate / 100)
decTotalTotal = decTotalDeposits + decTotalInterest
lblTotDeposit.Text = decTotalDeposits.ToString("C")
lblTot.Text = decTotalTotal.ToString("C")
lblTotInterest.Text = decTotalInterest.ToString("C")
Catch ex As Exception
MsgBox("Enter a Valid Number")
End Try
End Sub
This is how I implemented the loop for calculating total interest and total deposits correctly.
For index As Integer = 1 To intMonthsTotal Step 1
decTotalDeposits += decMonthlyDeposit
decTotalInterest += (decTotalDeposits + decTotalInterest) * ((decAnnualRate / 100) / 12)

Visual Basic Read from Keyboard

I am trying to implement a simple calculation to output Total Price using Visual Basic.NET
I want to read Original Price and Shipping Weight then use it in the calculation. The problem is,
When I enter any values, both variables will return only first digit
For example, if enter 23 it will return 2
Dim originalPrice As Double
Dim commissionPrice As Double
Dim shippingWeight As Double
Dim totalPrice As Double
Console.Write("Enter Original Price: ")
originalPrice = Double.Parse(Console.ReadLine(originalPrice))
Console.Write("Enter Shipping Weight: ")
shippingWeight = Double.Parse(Console.ReadLine(shippingWeight))
shippingWeight = shippingWeight * 7
If (originalPrice + shippingWeight >= 200) Then
commissionPrice = (originalPrice + shippingWeight) * 0.03
Else
commissionPrice = 5
End If
totalPrice = commissionPrice + originalPrice + shippingWeight
Console.WriteLine(originalPrice)
Console.WriteLine(commissionPrice)
Console.WriteLine(shippingWeight)
Console.WriteLine(totalPrice)
I think that your problem is that you are passing the variable to the Console.read()
In this way should work.
Dim originalPrice As Double
Dim commissionPrice As Double
Dim shippingWeight As Double
Dim totalPrice As Double
Console.Write("Enter Original Price: ")
originalPrice = Double.Parse(Console.ReadLine())
Console.Write("Enter Shipping Weight: ")
shippingWeight = Double.Parse(Console.ReadLine())
shippingWeight = shippingWeight * 7
If (originalPrice + shippingWeight >= 200) Then
commissionPrice = (originalPrice + shippingWeight) * 0.03
Else
commissionPrice = 5
End If
totalPrice = commissionPrice + originalPrice + shippingWeight
Console.WriteLine(originalPrice)
Console.WriteLine(commissionPrice)
Console.WriteLine(shippingWeight)
Console.WriteLine(totalPrice)
Console.Read()

VB.Net issue with double data range while performing a linear regression

I am performing linear regression using this data in VB.Net
1411478155,71.9700012207031
1411478150,72.9700012207031
1411478145,73.9700012207031
1411478140,74.9700012207031
1411478135,76.9700012207031
1411478130,78.9700012207031
1411478125,80.9700012207031
1411478120,81.9700012207031
1411478115,82.9700012207031
1411478110,84.9700012207031
1411478105,85.9700012207031
1411478100,88.9700012207031
The formula that I am using is this,
where x = UTC Seconds, y = Values
In the denominator, I am getting a zero value because both expressions in the denominator equal to a value of 2.8688695263517E+20.
I defined my series as,
Dim xs(12) As [Double]
Dim ys(12) As [Double]
I am not sure if the square brackets matter.
For now, I am not able to get results due to zero denominator. What data type should I use?
I expect more rows of data in future.
Edit:
Given below is the sub
`
Public Sub GetLinearRegressionParams(ByVal xs() As Double, ByVal ys() As Double, ByRef a As Double, ByRef b As Double)
Dim sumX As Double = 0
Dim sumY As Double = 0
Dim sumXY As Double = 0
Dim sumX2 As Double = 0
Dim n As Integer
n = 0
For index = 0 To xs.Length - 1
If xs(index) = Nothing Then
Else
sumX = sumX + xs(index)
sumY = sumY + ys(index)
sumXY = sumXY + xs(index) * ys(index)
sumX2 = sumX2 + xs(index) * xs(index)
n = n + 1
End If
Next
a = (sumY * sumX2 - sumX * sumXY) / (n * sumX2 - sumX * sumX)
b = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX)
End Sub
`

How to code Auto Loan calc with fixed months and interest? (VB)

I need to make an auto loan calculator that is only able to calculate 2.3% interest for 84 months. I've never made a calculator that didn't allow a user to input these amounts, so how do I code that part of the calc?
Dim res As Decimal = 100 ' Current value
Dim interest As Decimal = 1.89 / 100 ' 1.89%
For i As Integer = 1 To 89 'Months
Dim amr As Decimal = res * interest
res += amr
Next
MsgBox(res)
Depends on what you want to calculate.. Monthly paiement, equity, what is left to pay ?
Here's the formula to calculate the monthly paiement of a loan
Dim monthlyPaiement As Decimal
Dim loanAmount As Decimal
Dim interestRate As Decimal
Dim loanLengthInMonth As Decimal
loanAmount = 25000
interestRate = 1.9 / 100
loanLengthInMonth = 84
interestRate /= 12 ' Divide by number of month in a year
monthlyPaiement = loanAmount * ((1 + interestRate) ^ loanLengthInMonth) * interestRate / (((1 + interestRate) ^ loanLengthInMonth) - 1)