No sum at 2 decimal - vb.net

I just start it to make a program in vb.net in combination with SQL.
I have 5 textboxes with 5 values with 2 decimals, which are 10,50, 7,50, 8,50, 5,75, and 8,25. When I make a sum of this and put this in an other text box then it shows me the value 38,00 instead of 40,50.
My code is as follows:
Public Sub plussen()
Dim i1 As Integer
Dim i2 As Integer
Dim i3 As Integer
Dim i4 As Integer
Dim i5 As Integer
Dim i6 As Integer
For i1 = 5 To 20
i2 = i1 + 396
i3 = i1 + 496
i4 = i1 + 596
i5 = i1 + 696
i6 = i1 + 896
Me.Controls.Find("TextBox" + CStr(i1), True)(0).Text = (Val(Me.Controls.Find("TextBox" + CStr(i2), True)(0).Text) + Val(Me.Controls.Find("TextBox" + CStr(i3), True)(0).Text) + Val(Me.Controls.Find("TextBox" + CStr(i4), True)(0).Text) + Val(Me.Controls.Find("TextBox" + CStr(i5), True)(0).Text) + Val(Me.Controls.Find("TextBox" + CStr(i6), True)(0).Text)).ToString("F2")
Next
End Sub
I have put this in a loop because I have 20 x 5 boxes to calculate. This is working but as I said with this code it does not sums up the decimals.
Does someone have an idea about my issue?

This is super lame but from the documentation:
The Val function recognizes only the period (.) as a valid decimal
separator. When other decimal separators are used, as in international
applications, use CDbl or CInt instead to convert a string to a
number. To convert the string representation of a number in a
particular culture to a numeric value, use the numeric type's
Parse(String, IFormatProvider) method. For example, use Double.Parse
when converting a string to a Double.
So basically you need to use '.' instead of ',' in your textboxes or better yet switch from Val() to Double.Parse().
Ref: https://msdn.microsoft.com/en-us/library/9da280t0(v=vs.110).aspx

Change your val() to Convert.ToDecimal() and use CultureInfo("fr-FR") to specify the decimal format.
e.g.
Convert.ToDecimal("10,5", new CultureInfo("fr-FR"))

Related

Label a set of objects with (A->Z,AA->ZZ, AAA->ZZZ) in VBA

I have a set which has an unknown number of objects. I want to associate a label to each one of these objects. Instead of labeling each object with a number I want to label them with letters.
For example the first object would be labeled A the second B and so on.
When I get to Z, the next object would be labeled AA
AZ? then BA, BB, BC.
ZZ? then AAA, AAB, AAC and so on.
I'm working using Mapbasic (similar to VBA), but I can't seem to wrap my head around a dynamic solution. My solution assumes that there will be a max number of objects that the set may or may not exceed.
label = pos1 & pos2
Once pos2 reaches ASCII "Z" then pos1 will be "A" and pos2 will be "A". However, if there is another object after "ZZ" this will fail.
How do I overcome this static solution?
Basically what I needed was a Base 26 Counter. The function takes a parameter like "A" or "AAA" and determines the next letter in the sequence.
Function IncrementAlpha(ByVal alpha As String) As String
Dim N As Integer
Dim num As Integer
Dim str As String
Do While Len(alpha)
num = num * 26 + (Asc(alpha) - Asc("A") + 1)
alpha = Mid$(alpha, 2,1)
Loop
N = num + 1
Do While N > 0
str = Chr$(Asc("A") + (N - 1) Mod 26) & str
N = (N - 1) \ 26
Loop
IncrementAlpha = str
End Function
If we need to convert numbers to a "letter format" where:
1 = A
26 = Z
27 = AA
702 = ZZ
703 = AAA etc
...and it needs to be in Excel VBA, then we're in luck. Excel's columns are "numbered" the same way!
Function numToLetters(num As Integer) As String
numToLetters = Split(Cells(1, num).Address(, 0), "$")(0)
End Function
Pass this function a number between 1 and 16384 and it will return a string between A and XFD.
Edit:
I guess I misread; you're not using Excel. If you're using VBA you should still be able to do this will the help of an reference to an Excel Object Library.
This should get you going in terms of the logic. Haven't tested it completely, but you should be able to work from here.
Public Function GenerateLabel(ByVal Number As Long) As String
Const TOKENS As String = "ZABCDEFGHIJKLMNOPQRSTUVWXY"
Dim i As Long
Dim j As Long
Dim Prev As String
j = 1
Prev = ""
Do While Number > 0
i = (Number Mod 26) + 1
GenerateLabel = Prev & Mid(TOKENS, i, 1)
Number = Number - 26
If j > 0 Then Prev = Mid(TOKENS, j + 1, 1)
j = j + Abs(Number Mod 26 = 0)
Loop
End Function

Adding 4 byte values causes Overflow Exception

The following code raises a System.OverflowException
Dim b1 As Byte = 13
Dim b2 As Byte = 26
Dim b3 As Byte = 125
Dim b4 As Byte = 225
Dim i As Integer = (b1 + b2 + b3 + b4) \ 2
Why does this happen?
The value(s) doesn't get converted into an Integer until you assign it to the variable. This means that up until, and including, the \ 2 part everything is still of type Byte.
To make this work you've got to convert at least the first variable into an Integer, so that additional numbers can be added to it and go beyond 255.
Dim i As Integer = (CType(b1, Integer) + b2 + b3 + b4) \ 2
Online test: https://dotnetfiddle.net/Lxmx2S
Be aware that since this respects the order of mathematical operations, you must convert all the instances of too small types that are calculated before the others. For instance if you changed your operation to this:
Dim i As Integer = (CType(b1, Integer) + b2 * b3 + b4) \ 2
It would also throw an error because b2 * b3 is calculated before b1 + b2, and thus you would have to change it to:
Dim i As Integer = (CType(b1, Integer) + CType(b2, Integer) * b3 + b4) \ 2

How to generate a 26-character hex string that equals to 106 bits and ((53 Ones - 53 Zeros) in binary)

I am looking for a way to generate a hexadecimal string that equals out to 106 bits, more specifically fifty three 1's and fifty three 0's after each hex char is converted to binary and added together. I'd like to keep it as random as possible considering the parameters of the request. How would I go about keeping an eye on the construction of the string so that it equals out the way I want?
For example:
(a8c05779f8934b14ce96f8aa93) =
(1010 1000 1100 0000 0101 0111 0111 1001 1111 1000 1001 0011 0100
1011 0001 0100 1100 1110 1001 0110 1111 1000 1010 1010 1001 0011)
One option is to create a list with an equal number of 0s and 1s and then sort it with an array of random keys:
Sub Main()
' Start with a list of 53 0's and 1's
Dim bitsList = New List(Of Integer)
For i = 1 To 53
bitsList.Add(1)
bitsList.Add(0)
Next
Dim bits = bitsList.ToArray()
' Create list of random keys
Dim keys = New List(Of Integer)
Dim rand = New Random()
For i = 1 To bits.Count
keys.Add(rand.Next())
Next
' Sort bits by random keys
Array.Sort(keys.ToArray(), bits)
' Create hex string
Dim s = ""
For i = 1 To bits.Length - 4 Step 4
Dim digit = bits(i + 3) * 8 + bits(i + 2) * 4 + bits(i + 1) * 2 + bits(i)
s = s + Hex(digit)
Next
Console.WriteLine(s)
End Sub
You can place 52 ones randomly in a 104 bit number by keeping track of how many ones has been placed already and calculate the probability that the next digit should be one. The first digit always has 1/2 probability (52/104), then the second digit has 51/103 or 52/103 probability depending on what the first digit was, and so on.
Put the bits in a buffer, and when it is full (four bits), that makes a hexadecimal digit that you can add to the string:
Dim rnd As New Random()
Dim bin As New StringBuilder()
Dim buf As Integer = 0, bufLen As Integer = 0, left As Integer = 52
For i As Integer = 104 To 1 Step -1
buf <<= 1
If rnd.Next(i) < left Then
buf += 1
left -= 1
End If
bufLen += 1
If bufLen = 4 Then
bin.Append("0123456789abcdef"(buf))
bufLen = 0
buf = 0
End If
Next
Dim b As String = bin.ToString()
To make a 106 bit value, change these lines:
Dim buf As Integer = 0, bufLen As Integer = 0, left As Integer = 53
For i As Integer = 106 To 1 Step -1
The resulting string is still 26 characters, the two extra bits are in the buf variable. It has a value between 0 and 3 that you can use to create the 27th character, however that is done.
To add a 22 bit hash to the string, you can use code like this:
bin.Append("048c"(buf))
Dim b As String = bin.ToString()
Dim m As New System.Security.Cryptography.SHA1Managed
Dim hash As Byte() = m.ComputeHash(Encoding.UTF8.GetBytes(b))
'replace first two bits in hash with bits from buf
hash(0) = CByte(hash(0) And &H3F Or (buf * 64))
'append 24 bits from hash
b = b.Substring(0, 26) + BitConverter.ToString(hash, 0, 3).Replace("-", String.Empty)

Generate random string in text field

We have that old software (made by one of the first employees many years ago) in company that uses Microsoft Access to run. Boss asked me to add a random string generation in the specific text box on click but i have no idea how to do that. I dont have any Microsoft Access programming experience, thats why i am askin you to help.
I managed to create button and text field so far. Thats where it stops. I also managed to access the code for the button action:
Private Sub command133_Click()
End Sub
This is one way, will work in Access VBA (which is an older basic than vb.net). It will generate a string with letters and numbers.
Sub test()
Dim s As String * 8 'fixed length string with 8 characters
Dim n As Integer
Dim ch As Integer 'the character
For n = 1 To Len(s) 'don't hardcode the length twice
Do
ch = Rnd() * 127 'This could be more efficient.
'48 is '0', 57 is '9', 65 is 'A', 90 is 'Z', 97 is 'a', 122 is 'z'.
Loop While ch < 48 Or ch > 57 And ch < 65 Or ch > 90 And ch < 97 Or ch > 122
Mid(s, n, 1) = Chr(ch) 'bit more efficient than concatenation
Next
Debug.Print s
End Sub
Try this function:
Public Function GetRandomString(ByVal iLength As Integer) As String
Dim sResult As String = ""
Dim rdm As New Random()
For i As Integer = 1 To iLength
sResult &= ChrW(rdm.Next(32, 126))
Next
Return sResult
End Function
Workin on #Bathsheba code, I did this. It will generate a random string with the number of characters you'd like.
Code :
Public Function GenerateUniqueSequence(numberOfCharacters As Integer) As String
Dim random As String ' * 8 'fixed length string with 8 characters
Dim j As Integer
Dim ch As Integer ' each character
random = ""
For j = 1 To numberOfCharacters
random = random & GenerateRandomAlphaNumericCharacter
Next
GenerateUniqueSequence = random
End Function
Public Function GenerateRandomAlphaNumericCharacter() As String
'Numbers : 48 is '0', 57 is '9'
'LETTERS : 65 is 'A', 90 is 'Z'
'letters : 97 is 'a', 122 is 'z'
GenerateRandomAlphaNumericCharacter = ""
Dim i As Integer
Randomize
i = (Rnd() * 2) + 1 'One chance out of 3 to choose one of 3 catégories
Randomize
Select Case i
Case 1 'Numbers
GenerateRandomAlphaNumericCharacter = Chr(Rnd() * 9 + 48)
Case 2 'LETTERS
GenerateRandomAlphaNumericCharacter = Chr(Rnd() * 25 + 65)
Case 3 'letters
GenerateRandomAlphaNumericCharacter = Chr(Rnd() * 25 + 97)
End Select
End Function
I use it with random number of characters, like this :
'Generates random Session ID between 15 and 30 alphanumeric characters
SessionID = GenerateUniqueSequence(Rnd * 15 + 15)
Result :
s8a8qWOmoDvC4jKRjPr5hOY12u 26
TB24qZ4cNfr6EdyY0J 18
6LZRQ9P5WHLNd71LIdqJ 20
KPN0RmlhhJKnVzPTkW 18
R2pNOKWJMKl9KpSoIV2egUNTEb1QC2 30
X8jHuupP6SvEI8Dt2wJi 20
NOTE: This is still not completely random. It will give a higher count of numbers than normal as approx 1/3 of all chars generated will be numbers.
Normally distribution will look like:
10 numbers plus 26 lowercase plus 26 uppercase = 62 possible chars.
Numbers will normally be 10/62 parts of the string or 1/6.2
With the code
i = (Rnd() * 2) + 1 'One chance out of 3 to choose one of 3 catégories
the count of numbers is pushed up to 1/3 (on average)
Probably not too much of a worry - unless you are trying to beat the NSA and then you have decreased your range significantly.

Getting NaN for a double datatype

I am trying to run some mathematical formula which has large values, so I am using the Double datatype. But still I am getting the answer as NaN if I input large values. So how can I solve this?
For example, if I pass Varx=3 and countx=1230 I get the result as NaN.
Public Function EulerForPro(ByVal Varx As Integer, ByVal Countx As Integer) As Double
Dim Result1 As Double = 1
Dim Result2 As Double = Varx
Dim Result As Double = 0
For i = 1 To Countx
Result1 = Result1 + (Math.Pow(-1, i) * Math.Pow(Varx, (2 * i)) / factx(2 * i))
Next
For i = 1 To Countx
Result2 = Result2 + (Math.Pow(-1, i) * Math.Pow(Varx, ((2 * i) + 1)) / factx((2 * i) + 1))
Next
Result = Result1 + Result2
Label2.Text = Result1
Label3.Text = Result2
Label4.Text = Result
End Function
Use the logarithm of the results. It is standard practice for large numbers.
So instead of multiplying a*b (which causes overflow), use
Y = log(a) + log(b)
You could try using the Decimal data type instead. It can hold an integer value of approximately 7,9 x 10^28 (the exact number is 2^96 - 1, since it can use 96 bits of its 128 for storing the integer part of a value). However, it's a complex data type and you should carefully consider how to use it in your code. Not all implicit conversions work, especially when using Double.
See MSDN on decimal for exact specifications of Decimal.