By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,610 Members | 1,957 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,610 IT Pros & Developers. It's quick & easy.

I Need an IsNumeric Method

P: n/a
Hello,

Does anyone have a good/reliable approach to implementing an IsNumeric()
method that accepts a string that may represent a numerical value (eg. such
as some text retrieved from an XML file)? Thus if you pass it "1" or
"5.12345" it returns true, but "1b3q" it returns false? I know VB has this
sort of function, but was wondering how to implement something similar in
C#. I suppose I could use the Convert methods and catch any exceptions to
determine this, but is there a better technique?

TIA,

--
John C. Bowman
Software Engineer
Thermo Electron Scientific Instruments Div.
<Remove this before reply> jo*********@thermo.com
Nov 15 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
<"John Bowman" <<Remove this before reply> jo*********@thermo.com>>
wrote:
Does anyone have a good/reliable approach to implementing an IsNumeric()
method that accepts a string that may represent a numerical value (eg. such
as some text retrieved from an XML file)? Thus if you pass it "1" or
"5.12345" it returns true, but "1b3q" it returns false? I know VB has this
sort of function, but was wondering how to implement something similar in
C#. I suppose I could use the Convert methods and catch any exceptions to
determine this, but is there a better technique?


Simplest way: try to convert and catch the exception
Next simplest way: use a regular expression to weed out some dodgy
values, then try to convert and catch the exception
Fastest way: write a hand-crafted routine to weed out some dodgy
values, then try to convert and catch the exception

It's actually not too difficult to write a routine to do this, but you
need to be careful of a few things:

o Do you want +5 to be okay?
o How about -5?
o How about whitespace?
o Don't forget that .5 is generally considered okay, so don't
require digits before dots
o What about 1,5 in some European countries? What culture are you
interested in?

Generally, you should rule things out cautiously - it's okay to allow
dodgy values as they'll be caught when you try the conversion, but it's
not okay to reject any valid values, so err on the side of caution.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2

P: n/a
Jon,

Thanks for the help. I've whipped together a simple routine that may mostly
work for my purposes. It probably doesn't work in ALL cases, but for the
type of data I'll be encountering, I think it'll work... except for 1 thing.
I can't get it to work w/ scientific notation. I've included the code below:

The following calls return true correctly:
IsNumeric("1");
IsNumeric("1.0");
IsNumeric("5.12345678910123456");
IsNumeric("123456789");
IsNumeric("-1.2345");
IsNumeric("1-34bq55.5678");

The following calls return false incorrectly:
IsNumeric("1.234+e5");
IsNumeric("-1.234+e-5");
IsNumeric("5+e2");
public bool IsNumeric(string Str)
{
bool bTmp = false;
try
{
long lTmp = 0L;
double dTmp = 0.0D;
float fTmp = 0F;
int nTmp = 0;

bool bLong = false;
bool bDouble = false;
bool bFloat = false;
bool bInt = false;

try
{
//Try a long conversion.
lTmp = Int64.Parse(Str);
bLong = true;
}
catch(Exception eLong)
{
eLong = eLong;
}

try
{
//Try a double conversion.
dTmp = Double.Parse(Str);
bDouble = true;
}
catch(Exception eDouble)
{
eDouble = eDouble;
}

try
{
//Try a float conversion.
fTmp = Single.Parse(Str);
bFloat = true;
}
catch(Exception eFloat)
{
eFloat = eFloat;
}

try
{
//Try an int conversion.
nTmp = Int32.Parse(Str);
nTmp = Int16.Parse(Str);
bInt = true;
}
catch(Exception eInt)
{
eInt = eInt;
}

//Were any conversions succesful?
if((bLong == true) ||
(bDouble == true) ||
(bFloat == true) ||
(bInt == true))
{
bTmp = true;
}

}
catch(Exception eAll)
{
//Catch everything that goes wrong and return false;
eAll = eAll;
}

return bTmp;
}
I also, tried using something like the following to get the scientific
notation to work:

dTmp = (double)Convert.ChangeType(Str, typeof(double));

but alas it didn't work either. Any ideas/thoughts?
TIA,

John
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
<"John Bowman" <<Remove this before reply> jo*********@thermo.com>>
wrote:
Does anyone have a good/reliable approach to implementing an IsNumeric()
method that accepts a string that may represent a numerical value (eg. such as some text retrieved from an XML file)? Thus if you pass it "1" or
"5.12345" it returns true, but "1b3q" it returns false? I know VB has this sort of function, but was wondering how to implement something similar in C#. I suppose I could use the Convert methods and catch any exceptions to determine this, but is there a better technique?


Simplest way: try to convert and catch the exception
Next simplest way: use a regular expression to weed out some dodgy
values, then try to convert and catch the exception
Fastest way: write a hand-crafted routine to weed out some dodgy
values, then try to convert and catch the exception

It's actually not too difficult to write a routine to do this, but you
need to be careful of a few things:

o Do you want +5 to be okay?
o How about -5?
o How about whitespace?
o Don't forget that .5 is generally considered okay, so don't
require digits before dots
o What about 1,5 in some European countries? What culture are you
interested in?

Generally, you should rule things out cautiously - it's okay to allow
dodgy values as they'll be caught when you try the conversion, but it's
not okay to reject any valid values, so err on the side of caution.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #3

P: n/a
Hi John,

"John Bowman jo*********@thermo.com>" <<Remove this before reply> wrote in
message news:uK*************@tk2msftngp13.phx.gbl...
Jon,

Thanks for the help. I've whipped together a simple routine that may mostly work for my purposes. It probably doesn't work in ALL cases, but for the
type of data I'll be encountering, I think it'll work... except for 1 thing. I can't get it to work w/ scientific notation. I've included the code

below:

Given this routine:

private static bool IsNumeric(string inputValue)
{
NumberStyles numerStyle =
NumberStyles.AllowExponent |
NumberStyles.AllowThousands |
NumberStyles.AllowDecimalPoint |
NumberStyles.AllowLeadingSign;

double outputValue;

return Double.TryParse(
inputValue,
numerStyle,
CultureInfo.InvariantCulture,
out outputValue);
}
The following inputs are recognized as numeric (notice the difference in
exponent notation from your inputs):

"1"
"1.0"
"5.12345678910123456"
"123456789"
"-1.2345"
"1.234e+5"
"-1.234e-5"
"5e+2"

The following are not recognized as numeric:

"1-34bq55.5678" (you said this was correctly identified as numeric,
but it's not a notation I am familiar with)
"1.234+e5" (seems to choke on the "+" between the base and exponent)
"-1.234+e-5" (same here)
"5+e2" (and here)

The other benefit to using Double.TryParse, besides being able to be
specific about what number formats you will accept, is that it won't throw
an exception, which should make it perform better. Hope this helps.

Regards,
Dan
Nov 15 '05 #4

P: n/a
Daniel,

Thanks for the additional insight & suggestion.
"1-34bq55.5678" (you said this was correctly identified as numeric, but it's not a notation I am familiar with)
Oops, I put this one in the wrong catagory, it correctly returns false,
using my original code.. aka, it decided correctly.
"1.234+e5" (seems to choke on the "+" between the base and exponent) "-1.234+e-5" (same here)
"5+e2" (and here)


I think I may have come up with a mechanism to handle the scientific
notation. I'm going to try something like the following.

Using a Regex.Split call atttempt to split the string into the base &
exponent parts.

If length of the split array == 2, then call IsNumeric() again, on the base
and on the exponent portions respectively to determine if they are both
numeric, if so then IsNumeric() should return true, else return false.

Else if split array length != 2, then it's not scientifc notation and the
other approach I already have worked out using the TryParse instead, should
be called to handle other possibilities.

Do you think that's reasonble?
TIA again,

John
Nov 15 '05 #5

P: n/a
Hi John,

"John Bowman jo*********@thermo.com>" <<Remove this before reply> wrote in
message news:%2****************@TK2MSFTNGP12.phx.gbl...
Daniel,

Thanks for the additional insight & suggestion. <snip> I think I may have come up with a mechanism to handle the scientific
notation. I'm going to try something like the following.

Using a Regex.Split call atttempt to split the string into the base &
exponent parts.

If length of the split array == 2, then call IsNumeric() again, on the base and on the exponent portions respectively to determine if they are both
numeric, if so then IsNumeric() should return true, else return false.

Else if split array length != 2, then it's not scientifc notation and the
other approach I already have worked out using the TryParse instead, should be called to handle other possibilities.

Do you think that's reasonble?


Yes, I think that would be reasonable. Another (possibly simpler, safer)
approach would be to modify the routine I posted to replace any occurances
of "+e" with just "e":

private static bool IsNumeric(string inputValue)
{
NumberStyles numberStyle =
NumberStyles.AllowExponent |
NumberStyles.AllowThousands |
NumberStyles.AllowDecimalPoint |
NumberStyles.AllowLeadingSign;

double outputValue;

return Double.TryParse(
inputValue.Replace("+e", "e"), // note change here.
numberStyle,
CultureInfo.InvariantCulture,
out outputValue);
}

Regards,
Dan
Nov 15 '05 #6

P: n/a
<"John Bowman" <<Remove this before reply> jo*********@thermo.com>>
wrote:
Thanks for the help. I've whipped together a simple routine that may mostly
work for my purposes. It probably doesn't work in ALL cases, but for the
type of data I'll be encountering, I think it'll work... except for 1 thing.
I can't get it to work w/ scientific notation. I've included the code below:
I'm not sure why you're trying for each of float, double, long and int.
Every int is also a long. Every float is also a double. I *suspect*
that every long is also parsed by double.Parse, even if the value
returned isn't the exact long - so just a single call to double.Parse
would give you the appropriate response.

However, to allow exponents you could use the version of Double.Parse
which takes a NumberStyles, and include the AllowExponent value.
I also, tried using something like the following to get the scientific
notation to work:

dTmp = (double)Convert.ChangeType(Str, typeof(double));

but alas it didn't work either. Any ideas/thoughts?


Can't say I've ever used that - but the code above should do you fine.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #7

P: n/a
Daniel,
Yes, I think that would be reasonable. Another (possibly simpler, safer) approach would be to modify the routine I posted to replace any occurances
of "+e" with just "e":


I was planning on incorporating that change ... <g>

Thanks again,
John
Nov 15 '05 #8

P: n/a
Jon,

Thanks for the additional info.
I'm not sure why you're trying for each of float, double, long and int.
Every int is also a long. Every float is also a double. I *suspect*
that every long is also parsed by double.Parse, even if the value
returned isn't the exact long - so just a single call to double.Parse
would give you the appropriate response.
I realize this, I only left them in there to help w/ the
debugging/illustration process ... didn't mean to confuse the issue.

However, to allow exponents you could use the version of Double.Parse
which takes a NumberStyles, and include the AllowExponent value.


This dovetails nicely w/ Daniel's suggestion... will do

I also, tried using something like the following to get the scientific
notation to work:

dTmp = (double)Convert.ChangeType(Str, typeof(double));

but alas it didn't work either. Any ideas/thoughts?


Can't say I've ever used that - but the code above should do you fine.


Just trying out other ideas, trying to get it to work.

I'm suspecting I can get this to work OK now. Thanks to you both for he
help.
--
John C. Bowman
Software Engineer
Thermo Electron Scientific Instruments Div.
<Remove this before reply> jo*********@thermo.com
Nov 15 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.