I am getting the error "Overflow." in Visual Basic 2010 - vb.net

Dim clicks As Integer
clicks = 0
If clicks >= 10000000000000000000 Then
a19.ForeColor = Color.FromArgb(0, 153, 0)
End If
10000000000000000000 and above gives the error.
Is there any way to have unlimited large length numbers?

You can use Long instead of Integer to allow you to go up to about 9 * 10E18 (9 followed by 18 zeros). Use the L suffix on literals if they are Long
Dim bigNumber as Long = 5000000000000000000L
If you want integers that can be any size at all, look at the BigInteger Structure. For example (the following requires a reference to the System.Numerics DLL as well as the statement Imports System.Numerics
Dim clicks As BigInteger = 0
'Code that updates click goes here
Dim limit As BigInteger = BigInteger.Parse("10000000000000000000")
If clicks >= limit Then
a19.ForeColor = Color.FromArgb(0, 153, 0)
End If
You can also use Double to hold number as large as 1E308, but it can't hold 308 decimal digits, so the numbers will only be approximations.

In Computer Science a number is most often represented as an integer. An integer is most often defined as a 32-bit signed integer, which means that the value can only hold up to a value from -(2^31) to (2^31)-1. To use bigger numbers, you might want to check other integer types. The most commonly used bigger integer, is the 64-bit integer, which can hold a value from -(2^63) to (2^63)-1.

Related

Why does re-ordering the operands in VBA avoid "Run-time Error 6: Overflow"?

I just want to know the reason for the run-time error: Overflow when running these VBA codes
Function target_time(Time) As Double
target_time = 1200 * 60 * Time
End Function
Sub Test()
x = target_time(24)
MsgBox x
End Sub
I already addressed this issue by rearranging the function formula into:
target_time = Time*1200 * 60
I just want to know why is repositioning the variable causes the runtime error overflow
Here's what VBA does:
1200 and 60 <-- Those are small enough to be a (16-bit) Integer, so I'll assume they are 16-bit Integer constants.
1200 * 60 <-- A multiplication of two 16-bit Integers yields an Integer - there is no automatic promotion to a 32-bit Long. Since 1200 * 60 = 72000 exceeds the maximum value of a 16-bit integer, the expression overflows.
On the other hand, Time * 1200 is not a multiplication of two 16-bit Integers, it's a multiplication of a "Variant containing an Integer" with an Integer. In this case, the result is automatically promoted to a "Variant containing a Long":
Dim v As Variant
v = 1200
Debug.Print TypeName(v) ' prints Integer
Debug.Print TypeName(v * 60) ' prints Long
Debug.Print TypeName(v * 6000000) ' prints Double(!)
The reason for this can be found in section 5.6.9.3 of the VBA spec:
If one or both operands have a declared type of Variant:
If the operator’s effective value type is Integer, Long, Single or Double, the operator’s
value type is the narrowest type of either Integer, Long or Double such that the
operator value is within the valid range of the type. If the result does not fit within
Double, runtime error 6 (Overflow) is raised.
As an additon to Heinzi's answer which addresses the OP's question I would like to add that I would add some of the following operators: CLng, CDbl to make sure that the result will be correct (or better closer to correct :-) )
Instead of target_time = 1200 * 60 * Time use target_time = CDbl(1200) * CDbl(60) * CDbl(Time).

Overflow Error evaluating arithmetic expression with integers in VBA

The following evaluates to 32760, an integer:
Debug.Print (20 * 1638 - 1)
But this raises an overflow error:
Dim t as Integer
t = 1639
Debug.Print (20 * t - 1)
It seems like this is implicitly expecting an Integer return value, because if I do either of the following, the error is avoided.
Dim t as Long OR Debug.print (20 * CLng(t) - 1) OR Debug.Print (20# * t - 1)
Is this behavior documented?
Is my assumption accurate? Namely, that arithmetic of integers implies an integer return value, and that simply introducing one Long or Double value in to the equation will avoid the error?
If my logic is correct, Dim or 'Dimension' is a way of telling the application that you expect use a variable of a certain type, and that type pertains to a certain amount of 'bits' (of memory).
This reserves a section of the system's memory, which has been allocated a certain amount of bits dependant on the variable type that you have instructed in your code. These bits then define how many (If you're familiar with C++ or similar then you will probably already know all this...)
An Integer is 16 bits in VBA and is a signed integer which means we can store negative values too, so the limit is 32,767 because this is the biggest number we can achieve with 16 bits:
(generally a variable can hold 2^n where n = number of bits)
unsigned 16 bits = 0 - 65,536 (2^16)
signed 16 bits = -32,768 - 32,767
32,767 = 111111111111111 (Binary)
32,768 = 1000000000000000 <--- note the extra bit
This extra bit is what causes the "overflow" error - because the amount of bits required to produce the number overflows the amount of bits that the memory has to store the number safely.
I don't think the method of the calculation is documented to this extent, however your code snippet:
Dim t as Integer
t = 1639
Debug.Print (20 * t - 1)
would require t to be first be multiplied by 20, resulting in a figure of 32,780:
20 * t = 20 * 1639 = 32,780
32,780 = 1000000000001100 (Binary)
which overflows the bit limit for the Integer data type. At this point the system throws an error before it has the chance to proceed with the rest of the calculation because it tries to multiply t whilst still in it's allocated memory address, for which only 16 bits of memory have been reserved.
Also, not declaring t as a type will force VBA to default to type Variant which will assess that t needs to have more memory allocated when the calculation runs and push it into the Long boundary automatically.
Update: It would appear that VBA will only permit the highest amount of bits held by a variable within the equation for the return value, as can be seen in this example:
Sub SO()
Dim t As Integer, c As Long
t = 1639
c = 20
Debug.Print (20 * (t - 1)) '// No Error
Debug.Print (c * (t - 1)) '// No Error
Debug.Print ((c * t) - 1) '// No Error
c = (20 * t - 1) '// Error
Debug.Print (20 * t - 1) '// Error
End Sub
Although I don't believe this is documented anywhere, it would lead one to believe that VBA limits memory usage to the highest amount of bits being used by a variable at any one time.

Generate A Unquie Id (GUID) That Is Only 25 Characters In Length

What is the best appraoch to generate unquie ID's (no special characters) that will be 25 characters in length? I was thinking of generating a GUID and taking a substring of that, but I dont know if thats the best idea for uniqueness.
This is for dissconnected systems use. Creating a primary key in a database will not work in my situation. I need to create a unquie ID manually
I tried this but I am seeing duplicates in the output for some reason. So it doesnt seem too unquie even in this simple test..
Sub Main()
Dim sb As StringBuilder = New StringBuilder
For i As Integer = 1 To 100000
Dim s As String = GenerateRandomString(25, True)
sb.AppendLine(s)
sb.AppendLine(Environment.NewLine)
Next
Console.WriteLine(sb.ToString)
Console.ReadLine()
End Sub
Public Function GenerateRandomString(ByRef len As Integer, ByRef upper As Boolean) As String
Dim rand As New Random()
Dim allowableChars() As Char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMNOPQRSTUVWXYZ0123456789".ToCharArray()
Dim final As String = String.Empty
For i As Integer = 0 To len - 1
final += allowableChars(rand.Next(allowableChars.Length - 1))
Next
Return IIf(upper, final.ToUpper(), final)
End Function
You’re probably seeing duplicates because New Random() is seeded according to a system clock, which may not have changed by the next iteration.
Try a cryptographically secure RNG:
Const ALLOWABLE_ALL As String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Const ALLOWABLE_UPPERCASE As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Dim allowable As String = If(upper, ALLOWABLE_UPPERCASE, ALLOWABLE_ALL)
Dim result(len - 1) As Char
Dim current As Integer = 0
Using r As New Security.Cryptography.RNGCryptoServiceProvider()
Do
Dim buffer(255) As Byte
r.GetBytes(buffer)
For b As Byte In buffer
If b < allowable.Length Then
result(current) = allowable(b)
current += 1
If current = len Then Return New String(result)
End If
Next
Loop
End Using
This is also “more random” than your implementation in that letters aren’t weighted twice as heavily if upper is True.
A GUID might be 32 digits, but only if expressed in hexadecimal. That means it will only use characters 0-9 and A-F. If your string can use the entire alphabet then you can express the same GUID in fewer characters, especially if your string can be case sensitive.
See http://en.wikipedia.org/wiki/Globally_unique_identifier#Text_encoding for an example of alternative encoding, or http://web.archive.org/web/20100408172352/http://prettycode.org/2009/11/12/short-guid/ for example code. EDIT: Or Hans's method above which is much better. If you want to encode a GUID with only A-Z, a-z and 0-9 characters then you will need to look up Base-62 encoding (as opposed to base-64) because you only have 62 characters to encode into.
Stop trying to re-invent the wheel and just use .NET's built in GUID generator:
System.Guid.NewGuid()
which will generate a properly randomly seeded GUID, then simply sub-string it to your limit. Even better if you grab the last 25 chars, instead of the first 25.
PS: I don't consider this a great idea in general, because it's the entire GUID that's considered unique, not part of it, but it should satisfy what you want.

Overflow when multiplying Integers and assigning to Long

If I type the following into the immediate window I get Runtime error '6': Overflow.
MsgBox 24 * 60 * 60
Why is this?
This also fails:
Dim giveTime As Long
giveTime = 24 * 60 * 60
Why is this? giveTime is declared as a Long type, so 24 × 60 × 60 = 86400 should comfortably fit.
This is a really odd VBA quirk. I'm amazed I've never bumped into this.
Dim x As Long
x = 24 * 60 * 60 ' Overflow
x = 32767 + 1 ' Overflow.
x = 32768 + 1 ' Works fine!
So it looks like the * and + operators return an Integer in the first two examples. Sure enough, in the help file for the *operator (similar for the + operator):
result = number1 * number2
[...]
The data type of result is usually the same as that of the most precise expression.
Your literals 24, 60, and 60 are all of type Integer by default, so your * (or +) operator returns an Integer, which overflows because the result is greater than 32,767.
However, the literal 32,768 in the third example above defaults to Long type (since it is too large to be an Integer) and so the + returns a Long; no overflow.
The help file also says this:
If [...] the data type of result is an Integer variant that overflows its legal range [...] Then result is [...] converted to a Long variant.
Emphasis mine. Now this little rule sounds like common sense, and anyone would reasonably assume that it applies in your case. But your numbers are of type Integer, not Variant/Integer, so VBA doesn't apply this rule! Makes absolutely no sense to me, but that's how it is, and that's what the documentation says.
Solution: make one of the arguments of your * operator be of a type more precise than Integer (e.g. Long) and the problem will go away.
x = CLng(24) * 60 * 60 ' Result is Long, works fine.
In fact, and this is probably why I've never bumped into this quirk, I make a habit of declaring all of my Integer variables as Long instead, unless there is a specific concern that having Longs instead of Integers will cause problems with memory use or execution time (which is almost never the case). Granted, this won't help in cases when you operate on literals smaller than 32,768, because they default to Integer type.
You ask in a comment what a Variant/Integer is. Variant is basically a container type for any other data type. In the particular case where you make it contain an Integer:
Dim a As Variant ' a is now Empty
a = CInt(32767) ' a is now Variant/Integer
x = a + 1 ' works fine
But as noted above, a plain old Integer triggers the overflow error:
Dim b As Integer
b = 32767
x = b + 1 ' overflow
After every number, place #. It defines each number as a double. Think of it as, each number is placed in to memory for the calculation as sort of a temp variable.
If you define each number, it will allow enough space for the calculations.
eg:
Dim x As Long
x = 24# * 60# * 60#
or 24& 'indicates long

Best way to get the first digit from an integer of varying length in VB.NET

I am a newbie to programming and need some help with the basics.
I have a function which takes in an integer value. I want to be able to grab the first digit (or the first and second digits in some cases) of this integer and do something with it.
What is the best way in VB.NET to get the first digit of an integer (or the first and second)?
firstDigit = number.ToString().Substring(0,1)
firstTwoDigits = number.ToString().Substring(0,2);
int.Parse(firstDigit)
int.Parse(firstTwoDigits)
and so forth
I'm not well versed in VB syntax, so forgive me for the syntax errors:
dim i as integer
while i >= 10
i = i \ 10
end while
msgbox "i = " & i
Note, this prints the "first from the left" digit. Like, for "12345" it would print "1".
If you need the digits starting from the end of the integer, just get the modulu result for the tens or the hundreds, according to how many digits you need.
Dim n As Integer
n Mod 10
for the first digit, or:
n Mod 100
for the second and first digits.
If you need the first and second digits from the beginning of the number, there is another answer here which will probably help you.
for first digit you can use:
Dim number As Integer = 234734
Dim first = number.ToString.ToCharArray()(0)
for second digit you can use:
Dim number As Integer = 234734
Dim second = number.ToString.ToCharArray()(1)
This would work. You can use Math.ABS, absolute value, to eliminate negative. The number from left could be replaced by a function if you are using logic, like the overall length of the number, to determine how many of the leading characters you are going to use.
Dim number As Integer = -107
Dim result As String
Dim numberFromLeft As Integer = 2
result = Math.Abs(number).ToString.Substring(0, numberFromLeft)
This results in 10 it is a string but converting it back to a number is easy if you need to. If you need to keep track if it was positive or negative you could use the original value to apply that back to you parsed string.