IsNumeric Bug or misunderstanding?

G

Guest

All,

I think I may have uncovered a bug in the IsNumeric function, or at least a
misunderstanding on functionality.
I am writing a Schedule Of Classes Application for our campus and have a
section that lists the Times, Buildings and rooms for courses.

In this section I have a function called PadCell that takes3 parameters, one
the value, one a padd count and one a a boolean input called StripNumeric,
that if true, checks if the value is numeric so I can strip off leading 0's
on a value to make it more readable.

Private Function PaddCell(ByVal sValue As String, ByVal PaddCount As
String, Optional ByVal StripNumeric As Boolean = False) As String
Dim tString As String = sValue
If StripNumeric And IsNumeric(tString) Then
tString = CStr(CInt(tString))
While Left(tString, 1) = "0"
tString = Mid(tString, 2)
End While
End If
Dim i As Integer = Len(tString)
Dim j As Integer
For j = i + 1 To PaddCount
tString += " "
Next
Return tString
End Function

This function works fine when StripNumeric is False, and IfNumeric evaluates
properly, which is where I am having the problem.

The problem I have found is that if I have a room that starts with #E##,
where # is a number, such as 0E202, 1E100, or 0E500, IsNumeric returns this
value as true!. I have tested this in .NET 2.0. I am not sure if it occurs
in 1.1. If I pass in a literal "string" value, I would expect it to treat
it as a string, ot as another object type., To work around the problem, I had
to write a function, which I call IsNumeric2, which does a for loop on each
character in the string and checks if it IsNumeric and performs a boolean and
on a return value. If false found it bails out early as not to take up much
processing:

The function looks like:
Private Function IsNumeric2(ByVal sString) As Boolean
If Len(sString) = 0 Then Return False

Dim bNumber As Boolean = True
Dim iInt As Integer
For iInt = 1 To Len(sString)
bNumber = bNumber And IsNumeric(Mid(sString, iInt, 1))
If bNumber = False Then Exit For
Next

Return bNumber
End Function


Was this a known bug somewhere that I missed, or is this a special case I
may not be aware of. Note in the PaddCell function, the tString is being
passed as a string value, not numeric so IsNumeric should treat it as a
string I would think and not something in Scientific Notation, which is the
only use of E I could think of and I think that is what it is doing since
the function CInt("1E1") returns 10 instead of an InvalidCastException. If
this is the case, is there a way I can FORCE it to evaluate as string
directly?



Thanks,
Nathan
 
C

Cor Ligthert [MVP]

Nathan,

This is the reason that Herfried often write that IsNumeric does not forever
give the wanted result, however it is correct. IsNumeric will be evaluate
every value as true as there can be the slightest reason that it can be
true. In your sample with the exponent.

Cor
 
C

Chris

Nathan said:
All,

I think I may have uncovered a bug in the IsNumeric function, or at least a
misunderstanding on functionality.
I am writing a Schedule Of Classes Application for our campus and have a
section that lists the Times, Buildings and rooms for courses.

In this section I have a function called PadCell that takes3 parameters, one
the value, one a padd count and one a a boolean input called StripNumeric,
that if true, checks if the value is numeric so I can strip off leading 0's
on a value to make it more readable.

Private Function PaddCell(ByVal sValue As String, ByVal PaddCount As
String, Optional ByVal StripNumeric As Boolean = False) As String
Dim tString As String = sValue
If StripNumeric And IsNumeric(tString) Then
tString = CStr(CInt(tString))
While Left(tString, 1) = "0"
tString = Mid(tString, 2)
End While
End If
Dim i As Integer = Len(tString)
Dim j As Integer
For j = i + 1 To PaddCount
tString += " "
Next
Return tString
End Function

This function works fine when StripNumeric is False, and IfNumeric evaluates
properly, which is where I am having the problem.

The problem I have found is that if I have a room that starts with #E##,
where # is a number, such as 0E202, 1E100, or 0E500, IsNumeric returns this
value as true!. I have tested this in .NET 2.0. I am not sure if it occurs
in 1.1. If I pass in a literal "string" value, I would expect it to treat
it as a string, ot as another object type., To work around the problem, I had
to write a function, which I call IsNumeric2, which does a for loop on each
character in the string and checks if it IsNumeric and performs a boolean and
on a return value. If false found it bails out early as not to take up much
processing:

The function looks like:
Private Function IsNumeric2(ByVal sString) As Boolean
If Len(sString) = 0 Then Return False

Dim bNumber As Boolean = True
Dim iInt As Integer
For iInt = 1 To Len(sString)
bNumber = bNumber And IsNumeric(Mid(sString, iInt, 1))
If bNumber = False Then Exit For
Next

Return bNumber
End Function


Was this a known bug somewhere that I missed, or is this a special case I
may not be aware of. Note in the PaddCell function, the tString is being
passed as a string value, not numeric so IsNumeric should treat it as a
string I would think and not something in Scientific Notation, which is the
only use of E I could think of and I think that is what it is doing since
the function CInt("1E1") returns 10 instead of an InvalidCastException. If
this is the case, is there a way I can FORCE it to evaluate as string
directly?



Thanks,
Nathan

I agree that you should write your own routine for doing this but I
wonder if there is a better way of doing it:

Private Function IsNumeric2(ByVal sString) As Boolean
If sString.Length = 0 Then Return False
Dim bNumber As Boolean = True
For Each C As Char In sString.ToCharArray
If Asc(C) < System.Windows.Forms.Keys.D0 Or _
Asc(C) > System.Windows.Forms.Keys.D9 Then
Return False
End If
Next
Return
End Function
 
S

Stephany Young

From the documentation (VS2005) for IsNumeric:

Returns a Boolean value indicating whether an expression can be evaluated as
a number.

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.

IsNumeric returns False if Expression is of data type Date. It returns False
if Expression is a Char, String, or Object that cannot be successfully
converted to a number.

Yopu have hit the nail on the head in your last paragraph, in that a string
with a format of #E## as you describe is recognized as scientific format, or
rather shorthand for scientific format.

This can be demonstrated by typing (inside a method):

Dim _number As Double = 1E100
or
Dim _number As Double = 1e100

and note that the IDE will convert your typing to:

Dim _i As Double = 1.0E+100

I note, from the use of CInt(tString) in your code fragment, that if the
sValue parameter represents a number, you are expecting that it can be
successfully converted to the Integer type. This can better be tested by
using:

Dim _i as Integer
... Integer.TryParse(tString, _i)

A few other things you might want to investigate from a functionality and/or
efficiency point of view are the use of:

Overloading the method to negate the need for the Optional parameter

The AndAlso operator to 'short-circuit' the numeric test if StripNumeric
is false

The String.LTrim method to strip the leading zeroes when required

The String.PadLeft method to pad the result with leading spaces

Use of the latter 2 methods will negate the need for the loops.
 
M

Marina Levit [MVP]

What about calling something like Decimal.TryParse to see if the string can
be parsed as a numeric?
 
C

CMM

As others have pointed out, the "E" has special numerical meaning. I don't
think any other letters do.... sooooo, why don't you just do
IsNumeric(sString.Replace("E","X"))
 
G

Guest

Thank you all for your replies.

As per Stephany's suggestion, I found Integer.TryParse(tString, New Integer)
to work as expected. It returns false on the #E### results.

Also thanks to everyone for the performance increase suggestions.
It shaved a few things off. I guess this comes from my VB6 background and
not harnessing the full potential of the framework yet. I can probably find
other functions that would help as well.
 
J

Jim Wooley

Hello Marina Levit [MVP],
What about calling something like Decimal.TryParse to see if the
string can be parsed as a numeric?

As stated, Decimal.TryParse returns true and parses it as a scientific notation
value. I was starting to worry that 1F23 would parse successfully (as hex)
but luckily that is not the case by default. (I believe there is a way to
get the framework to parse this as true, but you have to set some FormatInfo
settings to handle it).

Jim Woole
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top