this error appears when trying to call a sub (An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll) - vb.net

i have a sub that will try to get random foods in the database, get the sum of these food's calories and check if they wont exceed the required calories.
most of the time the sub worked, but sometimes this error appears.
this is my code. it is kinda long.
Private Sub lunchgenerate()
Dim grams As Integer = DSgrams.Tables("grams").Rows(0).Item("grams")
Dim grams1 As Integer = DSricegrams.Tables("ricegrams").Rows(0).Item("grams")
Dim grams2 As Integer = DSgrams2.Tables("grams").Rows(0).Item("grams")
Dim calorieval As Decimal = foodcalories * grams
Dim calorieval1 As Decimal = ricecalories * grams1
Dim calorieval2 As Decimal = foodcalories2 * grams2
Dim carbval As Decimal = foodcarb * grams
Dim carbval1 As Decimal = ricecarb * grams1
Dim carbval2 As Decimal = foodcarb2 * grams2
Dim proteinval As Decimal = foodprotein * grams
Dim proteinval1 As Decimal = riceprotein * grams1
Dim proteinval2 As Decimal = foodprotein2 * grams
Dim fatval As Decimal = foodfat * grams
Dim fatval1 As Decimal = ricefat * grams1
Dim fatval2 As Decimal = foodfat2 * grams
Dim caloriepercent As Decimal = usercalories * 0.5
Dim mincalories As Decimal = caloriepercent - 300
Dim proteinpercernt As Decimal = userprotein * 0.5
Dim minprotein As Decimal = proteinpercernt - 20
Dim counter As Integer = 0
Dim counter1 As Integer = 0
Dim foodcalorietotal As Decimal = calorieval + calorieval1 + calorieval2
Dim foodproteintotal As Decimal = proteinval + proteinval1 + proteinval2
Dim carbtotal As Decimal = carbval + carbval1 + carbval2
Dim foodfattotal As Decimal = fatval + fatval1 + fatval2
If foodcalorietotal < mincalories Or foodcalorietotal > caloriepercent Then
counter = 0
Else
counter = 1
End If
If foodproteintotal < minprotein Or foodproteintotal > proteinpercernt Then
counter1 = 0
Else
counter1 = 1
End If
If counter = 1 And counter1 = 1 Then
'output to the form
Else
**lunchgenerate()**
End If
End If
End Sub
i think the error is when the lunchgenerate() sub is called again.
but just like what i said, most of the times it worked, but sometimes it freezes and then this error appears and then highlights the first line of my code which is
Dim DAlunchcategory As New SqlDataAdapter(lunchquery, CN)
Dim DSlunchcategory As New DataSet
DAlunchcategory.Fill(DSlunchcategory, "category_id")

Stack Overflow error happens when there is no space on the stack (part of the process memory used for local variables, parameter values, function results and a few other little things).
Often the code that produces this error does it by executing infinite recursion. If the code that you showed is complete lunchgenerate function, in the case when either counter or counter1 is not 1, lunchgenerate will be called again with exactly the same outcome, and again, and again, until it completely depletes space on the stack and exception is thrown. You need to have some escape logic to avoid it.

Related

vb.net calculation doesn't give decimals

hello im trying to do this calculation : [365!/((365^x)((365-x)!))]
the problem is when i do it it doesn't give me the decimals just the integer it give me 0 or 1 because the answer is 0
Public Class Form1
Private Function fact(ByVal n As Integer) As Numerics.BigInteger
Dim Z As New Numerics.BigInteger(1)
For i As Integer = 1 To n
Z = Z * i
Next
Return Z
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim min As Integer
Dim max As Integer
Dim ranum As Integer
Dim ind() As Integer
Dim ran As New Random
Dim F365 As New Numerics.BigInteger(0)
F365 = Numerics.BigInteger.Parse("25104128675558732292929443748812027705165520269876079766872595193901106138220937419666018009000254169376172314360982328660708071123369979853445367910653872383599704355532740937678091491429440864316046925074510134847025546014098005907965541041195496105311886173373435145517193282760847755882291690213539123479186274701519396808504940722607033001246328398800550487427999876690416973437861078185344667966871511049653888130136836199010529180056125844549488648617682915826347564148990984138067809999604687488146734837340699359838791124995957584538873616661533093253551256845056046388738129702951381151861413688922986510005440943943014699244112555755279140760492764253740250410391056421979003289600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
min = Integer.Parse(Tmin.Text)
max = Integer.Parse(Tmax.Text)
ranum = Integer.Parse(TRan.Text)
ReDim ind(ranum)
For x As Integer = 1 To ranum
ind(x) = ran.Next(min, max + 1)
Answer.Items.Add(ind(x))
Next
Dim P(ranum) As Numerics.BigInteger
Dim facts(ranum) As Numerics.BigInteger
For x = 1 To ranum
P(x) = 365 ^ (ind(x))
facts(x) = fact(365 - ind(x))
Next
Dim phenB(ranum) As Numerics.BigInteger
Dim phen(ranum) As Double
For x = 1 To ranum
phenB(x) = (P(x) * facts(x))
phen(x) = F365 / phenB(x)
tx.Text = phen(x) (here is the aswer)
Next
End Sub
End Class
The BigInteger class does not have a function to give a non-integer result for division. However, it does have BigInteger.Log, so, using these logarithmic identities:
ln(a⋅b) = ln(a) + ln(b)
ln(a/b) = ln(a) - ln(b)
ln(a^b) = b⋅ln(a)
we can perform the calculation like this:
Function SomeCalc(n As Integer) As Double
Dim lnF365 = BigInteger.Log(fact(365))
Dim lnPower = n * Math.Log(365)
Dim lnOtherFact = BigInteger.Log(fact(365 - n))
Return Math.Exp(lnF365 - lnPower - lnOtherFact)
End Function
where fact() is a pre-calculated array:
Option Strict On
Option Infer On
' ... other code ...
Dim fact(365) As BigInteger
' ... other code ...
Private Sub CalcFacts()
Dim z = BigInteger.One
For i = 1 To 365
z *= i
fact(i) = z
Next
End Sub
You could even have an array of pre-calculated logs of the factorials, instead of an array of the factorials. It depends on if you're using them elsewhere, and if there is any need for it to go a tiny tiny bit faster:
Function SomeCalc(n As Integer) As Double
Dim lnF365 = lnFact(365)
Dim lnPower = n * Math.Log(365)
Dim lnOtherFact = lnFact(365 - n)
Return Math.Exp(lnF365 - lnPower - lnOtherFact)
End Function
and
Dim lnFact(365) As Double
' ...
Private Sub CalcLnFacts()
Dim z = BigInteger.One
For i As Integer = 1 To largestNum
z *= i
lnFact(i) = BigInteger.Log(z)
Next
End Sub
That number 365 should be a named variable - I had no idea what a sensible name for it would be.

Access Run time error 6 Overflow

I have a form that does a simple calculation but the numbers are very large.
Example:
xml 96276480
graphics 2931829760
I've declared the data types as Long and even did a CLng(Me.txtGraphics.value) but I'm still getting the over flow error
These numbers are coming from text boxes.
Here's my code:
Dim sgm As Long
Dim XML As Long
Dim prv As Long
Dim base As Long
Dim IETM As Long
Dim Graphics As Long
Dim total As Long
Dim pgCnt As Long
Const CXML = 2.5
Const CSGM = 6
Const CGraphic = 339
Dim pcSGM As Long
Dim pcXML As Long
Dim pcGraphic As Long
If Me.txtSGM.value = "" Then
sgm = 0
Else
sgm = Me.txtSGM.value
End If
If Me.txtXML.value = "" Then
XML = 0
Else
XML = Me.txtXML.value
End If
If Me.txtGraphics.value = "" Then
Graphics = 0
Else
Dim pics As Long
pics = CLng(Me.txtGraphics.value)
Graphics = CLng(pics)
End If
If Me.txtTotal.value = "" Then
base = 0
Else
base = Me.txtTotal.value
End If
prv = base
pcSGM = (CLng(sgm) / 1024) / CSGM
pcXML = (CLng(XML) / 1024) / CXML
pcGraphic = (CLng(Graphics) / 1024) / CGraphic
'total calculated newest SGM & XML values
total = (CLng(pcSGM)) + (CLng(pcXML)) + (CLng(pcGraphic))
Thank you for the help,
Max
A long in VBA is a 32-bit signed integer (as opposed to a long in VB.Net, which is 64-bits). As such, the maximum value it can hold is 2147483647.
2931829760 is clearly larger, thus you get an overflow.
Either use Decimal and CDec instead of Long and CLng to cast them to decimals, or use Double and CDbl to cast them to doubles.
CDbl is likely faster, but can cause floating-point inaccuracy problems.
If you're sure your code will only be executed in the 64-bits variant of Access, you can also use CLngLng, which casts it to the LongLong data type, a 64-bits signed integer

Cannot figure out calculation

I need to make a phone bill program that would allow the user to calculate their phone bill. They would enter their minutes, texts and data allowance as well as how much they've used.
Each extra minute is 30p, each extra text is 10p and data used over the limit is £10.00, all added to the final cost.
The problem is that I cannot get the program to calculate the cost of each minute, I guess that after finding out how the minutes are calculated I will be able to do the same for the texts and the data.
Thanks for the help, much appreciated.
This is the problem
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub btn1TotalCost_Click(sender As Object, e As EventArgs) Handles btn1TotalCost.Click
Dim MinutesAllowed As Integer
Dim MinutesUsed As Integer
Dim TextsAllowed As Integer
Dim TextsUsed As Integer
Dim DataAllowed As Integer
Dim DataUsed As Integer
Dim MinutesTotalCost As Double
Dim TextsTotalCost As Double
Dim DataTotalCost As Double
Dim MonthlyCost As Double
Dim TotalCost As Double
MinutesAllowed = Val(txtBoxMinutesAllowed.Text)
MinutesUsed = Val(txtBoxMinutesUsed.Text)
TextsAllowed = Val(txtBoxTextsAllowed.Text)
TextsUsed = Val(txtBoxTextsUsed.Text)
DataAllowed = Val(txtBoxDataAllowed.Text)
DataUsed = Val(txtBoxDataUsed.Text)
MinutesTotalCost = Val(txtBoxTotalCost.Text)
TextsTotalCost = Val(txtBoxTotalCost.Text)
DataTotalCost = Val(txtBoxTotalCost.Text)
TotalCost = Val(txtBoxTotalCost.Text)
'Minutes
MinutesAllowed = Integer.Parse(txtBoxMinutesAllowed.Text)
MinutesUsed = Integer.Parse(txtBoxMinutesUsed.Text)
MonthlyCost = Val(txtBoxMonthlyCost.Text)
If MinutesAllowed >= MinutesUsed Then
MinutesTotalCost = 0
Else
MinutesTotalCost = (MinutesUsed - MinutesAllowed) * 0.3
End If
txtBoxTotalCost.Text = CType(MinutesTotalCost + MonthlyCost, String)
'Texts
TextsAllowed = Integer.Parse(txtBoxTextsAllowed.Text)
TextsUsed = Integer.Parse(txtBoxTextsUsed.Text)
MonthlyCost = Val(txtBoxMonthlyCost.Text)
If TextsAllowed >= TextsUsed Then
TextsTotalCost = 0
Else
TextsTotalCost = (TextsUsed - TextsAllowed) * 0.15
End If
txtBoxTotalCost.Text = CType(TextsTotalCost + MonthlyCost, String)
'Data
DataAllowed = Integer.Parse(txtBoxDataAllowed.Text)
DataUsed = Integer.Parse(txtBoxDataUsed.Text)
MonthlyCost = Val(txtBoxMonthlyCost.Text)
If DataAllowed >= DataUsed Then
DataTotalCost = 0
Else
DataTotalCost = (DataUsed - DataAllowed) + 10.0
End If
txtBoxTotalCost.Text = CType(DataTotalCost + MonthlyCost, String)
End Sub
End Class
MinutesTotalCost = MinutesUsed - MinutesAllowed * 0.3
Multiplication and division operators have precedence over the addition and subtraction operators.
You need to add brackets to the calculation.
MinutesTotalCost = (MinutesUsed - MinutesAllowed) * 0.3
You also overwrite the result of the calculation here:
MinutesTotalCost = txtBoxTotalCost.Text
Edit: Working code for just the minutes
Dim MinutesAllowed As Integer
Dim MinutesUsed As Integer
Dim MinutesTotalCost As Double
Dim MonthlyCost As Double
MinutesAllowed = Integer.Parse(txtBoxMinutesAllowed.Text)
MinutesUsed = Integer.Parse(txtBoxMinutesUsed.Text)
MonthlyCost = Val(txtBoxMonthlyCost.Text)
If MinutesAllowed >= MinutesUsed Then
MinutesTotalCost = 0
Else
MinutesTotalCost = (MinutesUsed - MinutesAllowed) * 0.3
End If
txtBoxTotalCost.Text = CType(MinutesTotalCost + MonthlyCost, String)
Val() returns a double so you need to use Integer.Parse() for int.
Double needs to be converted to string for the textbox.
Edit 2:
Since MonthlyCostdoesn't change you need the line
MonthlyCost = Val(txtBoxMonthlyCost.Text)
only once at the beginning.
You are always overwriting the value of txtBoxTotalCost. Just make a single calculation with all costs i.e.
txtBoxTotalCost.Text = CType(MinutesTotalCost + TextsTotalCost + DataTotalCost + MonthlyCost, String)

A first chance exception of type 'System.InvalidCastException' occurred in Microsoft.VisualBasic.dll on a combat simulator

I have an issue trying to program a simple combat simulation for a project that I and another person is working on.
Module Module1
Dim Player_Vitality As Integer
Dim PlayerReiatsu As Integer
Dim PlayerZanjustu As Integer
Dim PlayerHakuda As Integer
Dim PlayerHoho As Integer
Dim PlayerKido As Integer
Dim PlayerAbility As Integer
Dim Player_Physical_Damage As Integer
Dim Player_Spirit_Damage As Integer
Dim Player_Critical_Chance As Integer
Dim Player_Critical_Damage As Integer
Sub Main()
Call Shuhei()
End Sub
Sub Shuhei()
Dim Shuhei_reiatsu As Integer
Dim Shuhei_Vitality_TurnStart As Integer
Dim Shuhei_Vitality_TurnEnd As Integer
Dim Attack As String
Dim Kido As Integer
Dim Sword As Integer
Dim Shuhei_Temp As Integer
PlayerZanjustu = 40
PlayerHakuda = 50
PlayerKido = 50
PlayerAbility = 75
Shuhei_reiatsu = 80
Kido = Player_Spirit_Damage
Sword = Player_Physical_Damage
'Player_Vitality = 100
Shuhei_Vitality_TurnStart = 1000
Console.WriteLine("FIGHT 1")
Console.ReadLine()
Do While Shuhei_Vitality_TurnStart > 0
Player_Physical_Damage = ((PlayerZanjustu + PlayerHakuda) - Shuhei_reiatsu)
Player_Spirit_Damage = ((PlayerKido + PlayerAbility) - Shuhei_reiatsu)
'Player_Critical_Chance = ((PlayerZanjustu + PlayerHoho) - Shuhei_reiatsu) / 100
'Player_Critical_Damage = (PlayerZanjustu + PlayerHakuda) * 10
Shuhei_Temp = Shuhei_Vitality_TurnStart
Console.WriteLine("Shuhei has " & Shuhei_Temp & "Hp")
Console.WriteLine("Which attack do you want to use?")
Attack = Console.ReadLine
If Attack = "Kido" Or Kido Then
Shuhei_Vitality_TurnEnd = ((Shuhei_Temp) - Player_Spirit_Damage)
ElseIf Attack = "Sword" Or Sword Then
Shuhei_Vitality_TurnEnd = Shuhei_Temp - Player_Physical_Damage
Else
Console.WriteLine("Please choose an attack")
End If
Shuhei_Vitality_TurnEnd = Shuhei_Vitality_TurnStart
If Shuhei_Vitality_TurnStart <= 0 Then
Call FightEnd()
End If
Loop
Console.ReadKey()
End Sub
Sub FightEnd()
Console.WriteLine("Shuhei has been defeated")
Console.ReadKey()
End Sub
This is all copied down to the point in a new sub where there is deactivated junk with no purpose as of yet, so I doubt that is the issue, it is just the skeleton of the combat code but with ' in front to disable it. Then at the bottom the End Module command
In your IF Statement Attack could really never be "Kido" or Kido. You are comparing a string to a string or a string to an integer and that is likely your issue. Try converting Kido the variable to a string and that might supress the error.
Pseudo code:
If Attack = "Kido" Or Kido.ToString

startIndex cannot be larger than length of string. Parameter name: startIndex in vb.net

I have a piece of code that generates random characters. The problem is, every once in a while, it returns an error:
"startIndex cannot be larger than length of string.
Parameter name: startIndex"
How do I prevent this kind of error from happening?
Here's my code:
Friend Function gentCtrlChar()
Dim ran As New Random
Dim alpha As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Dim alpha2 As String = "ZYXWVUTSRQPONMLKJIHGFEDCBA"
Dim rdm As New Random
Dim genChar As String = ""
For i As Integer = 1 To 52
Dim selChar As Integer = rdm.Next(1, 28)
Dim selChar2 As Integer = rdm.Next(1, 28)
genChar = genChar + "" + alpha.Substring(selChar, 1) + "" + alpha2.Substring(selChar2, 1)
On Error Resume Next
Exit For
Next
Return genChar
End Function
as you can see, I tried putting the "On Error Resume Next" hoping that somehow, this will take care of the error for me. But sadly, It doesn't do it's job. Or am I using it the wrong way or for the wrong situation?
Any help?
Thanks!
this code:
Dim selChar As Integer = rdm.Next(1, 28)
will sometimes return a number that is longer (27 or 28) than the length of this string:
Dim alpha As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (only 26 characters long)
so, this is invalid when selChar is 26 or more.
alpha.Substring(selChar, 1)
Easiest fix is:
Dim selChar As Integer = rdm.Next(0, alpha.Length)
Dim selChar2 As Integer = rdm.Next(0, alpha2.Length)
Try this way. I think its cleaner and easy to understand. A - Z is the same as 65 - 90 on the ascii map so its very easy to convert an integer into a Char value. Then we just use the string builder to make this easier to read.
Dim rdm As New Random
Dim genChar As New StringBuilder()
For i As Integer = 1 To 52
Dim selChar As Char = Chr(rdm.Next(65, 90))
Dim selChar2 As Char = Chr(rdm.Next(65, 90))
genChar.Append(selChar)
genChar.Append(selChar2)
Next
Return genChar.ToString