vb.net calculation doesn't give decimals - vb.net

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.

Related

DataTable.Rows.Count always returns 0 - VB.NET

I'm trying to populate DataGridView cells with information from two (parent, child tables). Everything works just fine, except for this part table.Rows.Count. It always returns 0, no matter that I have one record in the table.
This is the code:
Private Sub Query__tbl_purchase_order_articlesDataGridView_CellEndEdit(sender As Object, e As DataGridViewCellEventArgs) Handles Query__tbl_purchase_order_articlesDataGridView.CellEndEdit
Dim table As DataTable = Orders_DBDataSet.Tables("tbl_list_of_articles")
Dim selectedRowCount As Integer = Query__tbl_purchase_order_articlesDataGridView.CurrentCell.RowIndex
Dim art_ID As Integer = CInt(Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(0).Value)
Dim art_ttl As String
Dim art_ttl_tr As String
Dim mu As String
Dim art_ttl_i As Integer
Dim art_ttl_tr_i As Integer
Dim mu_i As Integer
Dim art_ID_t_i As Integer
Dim art_ttl_t_i As Integer
Dim art_ttl_tr_t_i As Integer
Dim mu_t_i As Integer
Dim i As Integer
'search for column index in DataGridView
For i = 0 To Query__tbl_purchase_order_articlesDataGridView.Columns.Count - 1
If Query__tbl_purchase_order_articlesDataGridView.Columns(i).HeaderText.ToString = "article_name" Then
art_ttl_i = i
End If
If Query__tbl_purchase_order_articlesDataGridView.Columns(i).HeaderText.ToString = "article_name_tr" Then
art_ttl_tr_i = i
End If
If Query__tbl_purchase_order_articlesDataGridView.Columns(i).HeaderText.ToString = "masurement_unit" Then
mu_i = i
End If
Next
'search for column index in "table"
For i = 0 To table.Columns.Count - 1
If table.Columns(i).ColumnName.ToString = "article_ID" Then
art_ID_t_i = i
End If
If table.Columns(i).ColumnName.ToString = "article_name" Then
art_ttl_t_i = i
End If
If table.Columns(i).ColumnName.ToString = "article_name_tr" Then
art_ttl_tr_t_i = i
End If
If table.Columns(i).ColumnName.ToString = "masurement_unit" Then
mu_t_i = i
End If
Next
For i = 0 To table.Rows.Count
If art_ID = CInt(table.Rows(i).Item(art_ID_t_i).ToString()) Then
art_ttl = table.Rows(i).Item(art_ttl_t_i).ToString()
art_ttl_tr = table.Rows(i).Item(art_ttl_tr_t_i).ToString()
mu = table.Rows(i).Item(mu_t_i).ToString()
Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(art_ttl_i).Value = art_ttl
Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(art_ttl_tr_i).Value = art_ttl_tr
Query__tbl_purchase_order_articlesDataGridView.Rows(selectedRowCount).Cells(mu_i).Value = mu
Exit For
End If
Next
End Sub
Also, I tied to test it like this, but the result is the same. It can find a table index, but always return 0 as a table row count.
'test ========================================
Dim x, y As Integer
For x = 0 To Orders_DBDataSet.Tables.Count - 1
If Orders_DBDataSet.Tables(x).TableName.ToString = "tbl_list_of_articles" Then
y = x
End If
Next
x = 0
For Each row As DataRow In table.Rows
x = x + 1
Next
'============================================
x = Orders_DBDataSet.Tables(y).Rows.Count
Most of the times this happened to me because I was not actually using the instance of the dataset "connected" to the form. What does this mean? You either don't populate the dataset instance tied to the form in the Load event, or you are populating it but you are somehow using other instance of it. This has a higher chance of happening if you are sending data between forms as well.

Visual Basic loop sum of integers ^ 2 till user input. power of 2

I need help with one simple task:
Input an integer number n and output the sum: 1 + 2^2 + 3^2 + ... + n^2. Use input validation for n to be positive.
My code does not work and till now is:
Sub Main()
Dim inputNumber As Integer
Console.WriteLine("Please enter a positive number.")
inputNumber = Console.ReadLine()
If inputNumber <= 0 Then
Console.WriteLine("Please use only positive numbers > 0 !")
End If
Dim sum As Integer
Dim i As Integer = 1
For i = 1 To i <= inputNumber
sum = sum + (i * i)
i = i + 1
Next
Console.WriteLine(sum)
Console.ReadLine()
End Sub
Try these changes:
Dim inputNumber as Long ' not Integer. Also change sum, i.
...
inputNumber = CLng(Console.ReadLine) ' make it a number, not a string
...
Dim sum as Long ' yum
dim i as Long ' don't assign it here
for i = 1 to inputNumber ' don't use "<=" in a for loop
...
' i = i+1 ' Don't increment i within the loop, since the loop does that for you.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim Input As Integer
Input = TextBox1.Text
Dim i As Integer
i = 0
Dim x As Integer
x = 0
Dim y As Integer
y = 0
For a = 1 To Input
y = Math.Pow(a, (Input - i))
x = Math.Pow(a, (Input - i)) + x
i = i + 1
Next
Label1.Text = x
End Sub

VB.NET Compare each item in collection to every other item in collection - Threading

this is my first time posting so please accept my apologies if im not doing this right and please feel free to correct me for any formatting or posting guidelines. I am doing this in VB.Net with .NET Framework 4.5.2.
I have a large collection called gBoard in a class.
Private gBoard As Collection
It contains roughly 2000 instances of a class.
What i am trying to achieve is for each item in the class, i want to look at each other item in the class and then update the first item based on variables in the second.
Currently i have the following code:
In the main class:
Private gBoard As New Collection ' This is populated elsewhere in the code
Private Sub CheckSurroundings()
For i As Integer = 1 To (xBoxes)
For j As Integer = 1 To (yBoxes)
For x = 1 As Integer To (xBoxes)
For y = 1 As Integer To (yBoxes)
Tile(New Point(i, j)).CheckDistance(Tile(New Point(x, y)))
Next y
Next x
Next j
Next i
End Sub
Private Function Tile(ByVal aPoint As Point) As clsTile
Return gBoard.Item("r" & aPoint.Y & "c" & aPoint.X)
End Function
In clsTile i have the following (as well as other items):
Private Function SurroundingTerrain(ByVal aTer As String) As clsTerrain
Return mySurroundings.Item(aTer) ' a small collection (6 items of clsTerrain type)
End Function
Public Sub CheckDistance(ByRef aTile As clsTile)
SurroundingTerrain(aTile.Terrain).CheckDistance(CalcDistance(Location, aTile.Location))
End Sub
Private Function CalcDistance(ByVal myPoint As Point, ByVal aPoint As Point) As Double
Dim myReturn As Double = 0
Dim xDiff As Integer = 0
Dim yDiff As Integer = 0
Dim tDiff As Integer = 0
xDiff = Math.Abs(myPoint.X - aPoint.X)
yDiff = Math.Abs(myPoint.Y - aPoint.Y)
tDiff = xDiff + yDiff
myReturn = (MinInt(xDiff, yDiff) * 1.4) + (tDiff - MinInt(xDiff, yDiff))
Return myReturn
End Function
Private Function MinInt(ByVal a As Integer, ByVal b As Integer) As Integer
Dim myReturn As Integer = a
If b < myReturn Then
myReturn = b
End If
Return myReturn
End Function
in clsTerrain i have the following sub that is called:
Public Sub CheckDistance(ByVal aDist As Double)
If aDist < Distance Then
Distance = aDist
End If
End Sub
This runs and works file but as you can guess it runs so slow... I have been trying to work out how to make this run faster and i looked into threading/tasks but it doesnt seem to work. There are no errors but the objects don't appear to update correctly (or at all). The code i tried was:
In the main class:
Private Sub CheckSurroundings()
Dim tasks As New List(Of Task)
Dim pTile As clsTile
For Each pTile In gBoard
tasks.Add(Task.Run(Sub() TileToCheck(pTile)))
Next
Task.WaitAll(tasks.ToArray())
End Sub
Private Sub TileToCheck(ByRef aTile As clsTile)
For x As Integer = 1 To (xBoxes)
For y As Integer = 1 To (yBoxes)
aTile.CheckDistance(Tile(New Point(x, y)))
Next y
Next x
End Sub
Does anyone have any suggestions or ideas for how to get this to work?
Sorry for any headaches or facepalms caused...

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)

Convert 1DPointArray into 2DPointArray

I started a new project which loads and saves tilesets in style of ini-datas.
The problem is now, that it loads the tiles into a 1d- list, which got copied sorted into a 1d-array.
Now I am trying to convert this sorted 1d-array into a 2d-array.
My try:
LoadedTiles.Sort(Function(p1, p2) (p1.Position.X.CompareTo(p2.Position.X)))
LoadedTiles.Sort(Function(p1, p2) (p1.Position.Y.CompareTo(p2.Position.Y)))
Dim currentArray(AmountTiles) As Tile
currentArray = LoadedTiles.ToArray
Dim lengthX, lengthY As Integer
Dim yAxis As Integer = currentArray(0).Position.Y
For Each p In currentArray
If Not p.Position.Y = yAxis Then
lengthX = (p.Position.X / p.Size.Width)
lengthY = (currentArray(currentArray.Length - 1).Position.Y / p.Size.Width)
Else
lengthX = (currentArray(currentArray.Length - 1).Position.X / p.Size.Width)
lengthY = 0
End If
Next
MapTiles = New Tile(lengthX, lengthY) {}
Dim ii As Integer
For x = 0 To lengthX
For y = 0 To lengthY
MapTiles(x, y) = currentArray(ii)
If Not ii >= currentArray.Length - 1 Then
ii += 1
End If
Next
Next
This gives a wrong output.
See picture below:
http://www.directupload.net/file/d/3690/pz8x98jr_png.htm
Is it possible to do it right?
Thanks alot!
The k-th element in a 1D array can correspond to row i=k/N and column j=k%N where N is the number of columns. The reverse is k=i*N+j
Ok guys, I got it ( =
Public Class Form1
Dim List As New List(Of Point)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
List.Add(New Point(180, 360))
List.Add(New Point(180, 180))
List.Add(New Point(180, 540))
'Convert 1d to 2d
Dim count As Point = countXYAxis(List, 180)
MsgBox(count.ToString)
Dim p(count.X - 1, List.Count - 1) As Point
MsgBox(p.Length)
Dim rofl As Integer
For i = 0 To p.GetUpperBound(0)
For j = 0 To p.GetUpperBound(1)
p(i, j) = List(rofl)
If Not rofl >= List.Count - 1 Then
rofl += 1
End If
Next
Next
For Each t In p
MsgBox(t.ToString)
Next
End Sub
Private Function countXYAxis(ByVal pt As List(Of Point), ByVal size As Integer) As Point
Dim bufferY As New List(Of Integer)
Dim cP As New Point
For Each pts In pt
If Not bufferY.Contains(pts.Y) Then
bufferY.Add(pts.Y)
End If
Next
For i = 0 To pt.Count - 1
If pt(i).Y = bufferY(0) Then
Else
cP = New Point(pt(i).X / size, bufferY.Count)
End If
Next
Return cP
End Function
End Class