Integer.Parse vs. CInt - vb.net

Basically, I have been using both Integer.Parse and CInt in most of my daily programming tasks, but I'm a little bit confused of what the difference is between the two.
What is the difference between Integer.Parse and CInt in VB.NET?

CInt does a whole lot more than Integer.Parse.
CInt will first check to see if what it was passed is an integer, and then simply casts it and returns it. If it's a double it will try to convert it without first converting the double to a string.
See this from the help for CInt and other Type Conversion Functions
Fractional Parts. When you convert a
nonintegral value to an integral type,
the integer conversion functions
(CByte, CInt, CLng, CSByte, CShort,
CUInt, CULng, and CUShort) remove the
fractional part and round the value to
the closest integer.
If the fractional part is exactly 0.5,
the integer conversion functions round
it to the nearest even integer. For
example, 0.5 rounds to 0, and 1.5 and
2.5 both round to 2. This is sometimes called banker's rounding, and its
purpose is to compensate for a bias
that could accumulate when adding many
such numbers together.
So in short, it does much more than convert a string to an integer, e.g. applying specific rounding rules to fractions, short circuiting unnecessary conversions etc.
If what you're doing is converting a string to an integer, use Integer.Parse (or Integer.TryParse), if you're coercing an unknown value (e.g. a variant or object from a database) to an integer, use CInt.

Looking with ILDASM at some sample code you can see that CInt is converted to this call:
Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.Conversions::ToInteger(string)
Using .NET Reflector, you can extract this piece of code:
Public Shared Function ToInteger(ByVal Value As String) As Integer
Dim num As Integer
If (Value Is Nothing) Then
Return 0
End If
Try
Dim num2 As Long
If Utils.IsHexOrOctValue(Value, (num2)) Then
Return CInt(num2)
End If
num = CInt(Math.Round(Conversions.ParseDouble(Value)))
Catch exception As FormatException
Throw New InvalidCastException(Utils.GetResourceString("InvalidCast_FromStringTo", New String() { Strings.Left(Value, &H20), "Integer" }), exception)
End Try
Return num
End Function
You can see that internally it calls Conversions.ParseDouble.
Therefore, as already explained by Binary Worrier, use Integer.Parse for string coercing and CInt only for casting.

Here is a real difference :
Integer.parse("1.00") will thrown an error.
CInt("1.00") will work

The <Data Type>.Parse methods are used to extract a value of the type from a string that represents the value (e.g 2 from "2") The C<Data Type> functions operate on expressions and return a variant sub-typed to the desired type (e.g. CInt("2") OR CInt(SomeDouble + SomeDouble), etc.).

Related

IsNumeric() allowing minus at last of the values

I am using IsNumeric() function in my code to validate numbers.
IsNumeric(100) - true,
IsNumeric(-100) - true,
IsNumeric(+100) - true,
IsNumeric(100-) - true - I have doubt in this. (100-) Is this a valid number? IsNumeric () returns true to this value.
Dim latitude As String = "12.56346-"
If IsNumeric(latitude) Then
If (Convert.ToDouble(latitude) >= -90 And Convert.ToDouble(latitude) <= 90) Then
isValidLatitude.Text = "true"
Else
isValidLatitude.Text = "false"
End If
Else
isValidLatitude.Text = "false"
End If
Error while converting latitude to double
Input string was not in a correct format.
IsNumeric is from the Microsoft.VisualBasic namespace/dll, a bunch of helper stuff intended to help VB6 programmers get their arcane VB6 code /knowledge working on VB.NET
You'll note if you use other functions from the same dll such as Microsoft.VisualBasic.Conversion.Int(), or you use dedicated VB.NET converters such as CInt or CDbl these will also cope with a trailing minus sign and return a negative value
If you want to dispense with the old ways of VB6, use a numeric type's TryParse.. but all in, be consistent / if you use a function from Microsoft.VisualBasic to determine if a conversion can be made, use the vb conversion because within itself the package will be consistent but between Microsoft.VB and normal .net System there are some differences in behavior
Edit:
A couple of people have been wondering about the source code and how it uses TryParse, so why doesn't it work like using TryParse directly?
Microsoft.VisualBasic.Information.IsNumeric() uses Microsoft.VisualBasic.CompilerServices.DoubleType.TryParse() to determine whether an expression is numeric. This DoubleType.TryParse is not the same as Double.TryParse - it is a helper method again in the VB namespace that specifically sets the NumberStyles.AllowTrailingSign flag among many other flags. When parsing the number (first as non currency related, using Double.Parse, then if it fails a second attempt is made using adjusted values for currency related tests) this AllowTrailingSign flag will be considered in conjunction with other regional number formatting rules in determining if the passed in value is numeric
You'll note that on a machine obeying a USA number formatting culture, a string of "(100$)" is also declared to be numeric but calling Double.TryParse("(100$)", x) will also return false. The VB helper methods here are being a lot more liberal in what they accept than the System methods, because they're telling the System methods to be more liberal than they are by default
As noted, I've always regarded the Microsoft.VisualBasic namespace as a bunch of helper methods intended to allow terrible old VB6 code to be pasted into VB.NET and work with minimal fiddling. I wouldn't advocate using it for new projects and I remove the reference when I work on VB.NET - using it to support the VB6 notions of "just sling anything in, of any type, and it'll probably figure it out and work.. and if it doesn't we can always on error resume next" should be discarded in favour of precise and accurate about the operations executed and their intent
Note: my previous answers were wrong about assuming it was a bug. As the answer of #Damien_The_Unbeliever states, this function tries to validate the string as a lot of data types. And actually, the value "100-" is a valid Decimal number. That's why it returns true (as it's a "valid" Decimal) but gives a exception when converting to Double (as it's not a valid Double). #Damien_The_Unbeliever really deserves your +1 for pointing that.
From the documentation (showing all the data types that IsNumeric tries to validate):
IsNumeric returns True if the data type of Expression is Boolean, Byte, Decimal, Double, Integer, Long, SByte, Short, Single, UInteger, ULong, or UShort. It also returns True if Expression is a Char, String, or Object that can be successfully converted to a number. Expression can contain non-numeric characters. IsNumeric returns True if Expression is a string that contains a valid hexadecimal or octal number. IsNumeric also returns True if Expression contains a valid numeric expression that begins with a + or - character or contains commas.
Also, #CaiusJard did a nice search and pointed out that inner methods use a NumberStyles.AllowTrailingSign option, which allows this behavior.
Ok, now to the solution:
Just use a TryParse method, from your desired data type (int, long, etc...). The cool thing is that it'll behaves exactly as you expect, and if the parsing is successful, we have the parsed value already available to use!
if (Int32.TryParse(value, out int number))
{
// String is a valid number, and is already parsed in the 'number' variable!
}
else
{
// String is not a valid number!
}
Solution's VB.Net version:
Dim value As String = "12.56346-"
Dim number As Double = 0
If Double.TryParse(value, number) Then
' String is a valid number, and is already parsed in the "number" variable!
isValidLatitude.Text = "true"
Else
' String is not a valid number!
isValidLatitude.Text = "false"
End If
IsNumeric answers a question no sane person wants to ask. As quoted by Vitox's answer:
IsNumeric returns True if the data type of Expression is Boolean, Byte, Decimal, Double, Integer, Long, SByte, Short, Single, UInteger, ULong, or UShort. It also returns True if Expression is a Char, String, or Object that can be successfully converted to a number.
Note, it doesn't tell you that the given string can be converted to all numeric types. It tells you that the string can be converted to at least one numeric type. And for bonus bad style points, of course, it doesn't tell you which types the string can be converted to.
Decimal.Parse("100-") will execute perfectly well and give you a Decimal containing a value of -100.
So, it's not a bug, it's a bad function that has been retained for backwards compatibility reasons. Nowadays, we know better, and that we want to test whether a string can be converted to a specific data type, for which the TryParse family of functions have been designed.

CInt vs. Math.Round in Visual Basic .NET

What is the difference between:
Dim a As Integer = CInt(2.2)
and
Dim a As Integer = Math.Round(2.2)
?
CInt returns an integer but will round the .5 to nearest even number so:
2 = CInt(2.5)
4 = CInt(3.5)
Are both true, which might not be what you want.
Math.Round can be told to round away from zero. But returns a double, so we still need to cast it
3 = CInt(Math.Round(2.5, MidpointRounding.AwayFromZero))
There is bigger differences in CInt(), Int() and Round()... and others.
Round has parameters of rounding, so it is flexible and user friendly. But it do not change variable type. No "type conversion".
Meanwhile CInt() is a bit cryptic as it rounds too. And it is doing "Type conversion" to integer.
2 = Int(2.555), 3 = CInt(2.555)
2 = Int(2.5), 2 = CInt(2.5)
Some documentation states:
When the fractional part of expression is exactly .5, CInt always rounds it to the nearest even number. For example, .5 rounds to 0, and 1.5 rounds to 2.
But I do not like that "exact 0.5", in real word it is "0.5000001"
So, doing integer math (like calculating bitmaps address Hi and Lo bytes) do not use CInt(). Use old school INT(). Until you get to negative numbers... see the fix() function.
If there is no need to convert type, use floor().
I think all this chaos of number conversion is for some sort of compatibility with some ancient software.
The difference between those two functions is that they do totally different things:
CInt converts to an Integer type
Math.Round rounds the value to the nearest Integer
Math.Round in this instance will get you 2.0, as specified by the MSDN documentation. You are also using the function incorrectly, see the MSDN link above.
Both will raise an Exception if conversion fails, you can use Try..Catch for this.
Side note: You're new to VB.NET, but you might want to try switching to C#. I find that it is a hybrid of VB.NET & C++ and it will be far easier for you to work with than VB.NET.

math.floor is supposed to return integer

I am trying to get the integer part of a number after dividing two variables.
ie, get 3 if the value is 3.75
displaycount and itemcount are both integer variables.
Dim cntr As Integer
cntr = Math.Floor(Math.Abs(itemCount / displaycount))
That code produces a blue squiggly in VS2012 with the comment that "runtime errors may occur when converting Double to Integer" BUT Math.Floor is supposed to take a decimal or double and return an integer.
"Math.Floor is supposed to take a decimal or double and return an integer." No, it isn't. It returns a value of the same type as its argument. See the documentation, e.g. Math.Floor Method (Double).
I would have expected VS to suggest a fix of adding CInt() around the RHS of the assignment; did that not appear for you?
If you need an Integer as result, consider using either the CInt, Int or the Fix functions.
CInt rounds to the nearest integer using the bankers's rounding (n.5 rounds towards the closest even number).
Int removes the fractional parts. Negative numbers are truncated towards smaller numbers
Int(-8.4) = -9.
Fix removes the fractional parts. Negative numbers are truncated towards greater numbers
Fix(-8.4) = -8.
See Conversion.Int Method and Type Conversion Functions (Visual Basic).

VBA: Does Str(myString) do the same as Str(CDbl(myString))?

Question: Can I assume that Str(myString) will always return the same result as Str(CDbl(myString)) (assuming that myString is statically typed as a string)?
Context:
I am trying to understand VBA's implicit conversions. So far, it appears to me that Str(myString)
implicitly parses myString into a double (culture-sensitive) and then
converts the result into a culture-insensitive string.
For example, using a German locale (i.e. using , as the decimal separator), it holds that
" 1.2" = Str(1.2) = Str("1,2") = Str(CDbl("1,2"))
Since these implicit conversions contain a lot of "magic" to me, I am trying to rewrite a procedure that uses an implicit conversion (Str(myString)) to one using explicit conversion without changing the behavior.
Unfortunately, the documentation is wrong and, thus, useless. (The documentation claims that the argument to Str is interpreted as a Long, which is obviously rubbish: If that were the case Str(1.2) could never yield " 1.2".)
Your statement is true. Str(x) and Str(Cdbl(x)) give identical result provided that x is String data type and contains a valid number.
I made a small test to get convinced.
I used Excel, but it holds the same with Access.
Public Function myStr(txt As String) As String
myStr = Str(txt)
End Function
Public Function myStrCDbl(txt As String) As String
myStrCDbl = Str(CDbl(txt))
End Function
I tried with some key values (0, 1.2, 1E+307, 1E-307, ...) : result of myStr and myStrCDbl are always identical.
I also agree with you that the documentation is wrong. If Str() argument would be interpreted as Long, then Str(1.2) would give "1", because Long is an integer type.
In the mean time, I've found the VBA language specification and can confirm that the spec also answers the question with "yes":
CDbl, when receiving a string, performs a Let-coercion to Double:
If the value of Expression is not an Error data value return the Double data value that is the result of Expression being Let-coerced to Double.
Str, when receiving a string, first performs a Let-coercion to Double and then applies Str:
[If Number is a String,] the returned value is the result of the Str function applied to the result of Let-coercing Number to Double.

Cleanest way to convert a `Double` or `Single` to `Integer`, without rounding

Converting a floating-point number to an integer using either CInt or CType will cause the value of that number to be rounded. The Int function and Math.Floor may be used to convert a floating-point number to a whole number, rounding toward negative infinity, but both functions return floating-point values which cannot be implicitly used as Integer values without a cast.
Is there a concise and idiomatic alternative to IntVar = CInt(Int(FloatingPointVar));? Pascal included Round and Trunc functions which returned Integer; is there some equivalent in either the VB.NET language or in the .NET framework?
A similar question, CInt does not round Double value consistently - how can I remove the fractional part? was asked in 2011, but it simply asked if there was a way to convert a floating-point number to an integer; the answers suggested a two-step process, but it didn't go into any depth about what does or does not exist in the framework. I would find it hard to believe that the Framework wouldn't have something analogous to the Pascal Trunc function, given that such a thing will frequently be needed when performing graphical operations using floating-point operands [such operations need to be rendered as discrete pixels, and should be rounded in such a way that round(x)-1 = round(x-1) for all x that fit within the range of +/- (2^31-1); even if such operations are rounded, they should use Floor(x+0.5), rather than round-to-nearest-even, so as to ensure the above property]
Incidentally, in C# a typecast from Double to Int using (type)expr notation uses round-to-zero semantics; the fact that this differs from the VB.NET behavior suggests that one or both languages is using its own conversion routines rather an explicit conversion operator included in the Framework. It would seem likely that the Framework should define a conversion operator? Does such an operator exist within the framework? What does it do? Is there a way to invoke it from C# and/or VB.NET?
After some searching, it seems that VB has no clean way of accomplishing that, short of writing an extension method.
The C# (int) cast translates directly into conv.i4 in IL. VB has no such operators, and no framework function seems to provide an alternative.
Usenet had an interesting discussion about this back in 2005 – of course a lot has changed since then but I think this still holds.
You can use the Math.Truncate method.
Calculates the integral part of a specified double-precision floating-point number.
For example:
Dim a As double = 1.6666666
Dim b As Integer = Math.Truncate(a) ' b = 1
I know this is an old case but I saw no one suggest the Math.Round() function.
Yes Math.Round takes a double and returns a double. However it returns a number that has been rounded to a whole number. It should easily and concisely convert to an integer using cInt. Would that suffice?
cInt(math.round(10000.54564)) ' = 10001
cInt(math.round(10000.49564)) ' = 10000
You may need extract the Int part of a float number:
float num = 12.234;
string toint = "" + num;
string auxil = toint.Split('.');
int newnum = Int.Parse(auxil[0]);