 |
|
 |
Whilst I wasn't particularly looking for numeric checks (I use Integer.TryParse() BTW, it's a lot better). This article showed me how to force a particular culture into my application
|
|
|
|
 |
|
 |
The real problem here is that the system's settings are stupid - if comma is both decimal separator and digit grouping symbol, "100,123" is possibly just over a hundred, possibly just over a hundred thousand. So why worry about whether it's a number? If you cannot tell what a 'number' is supposed to be, you're in big trouble. So is any other application that deals with numbers. (And the result of IsNumeric is correct in its own way - an indeterminate number isn't really a number!)
I think you'd be much better off checking for silly settings like this when your app starts. If you find them, the app explains the silliness to the user firmly but politely, and then terminates. The worst that can happen is that an irate customer phones the support desk to complain, and eventually gets told of their own stupidity. You'll be doing them a service because most apps won't cope with the silly setting, and will either crash or start logging mysterious errors.
(Evidence: the SQL server v 2005 version of SQL Server Management studio was incapable of doing "Open table" on a table with numbers in it after I put this kind of setting into control panel.)
-- modified at 6:54 Friday 23rd November, 2007
|
|
|
|
 |
|
 |
I agree, but only partially.
While I can accept to see "False" as a result of this code:
MessageBox.Show(IsNumeric("100,123").ToString())
when IsNumeric() isn't able to decide (due to user's silly settings),
I still consider unacceptable to see "False" as a result of:
MessageBox.Show(IsNumeric("12345").ToString())
Regards, AV
|
|
|
|
 |
|
 |
.NET can slove this problem, but in old vb6.0, how to solve the like this IsNumberic() error?
If have any easy method, please tell me.
|
|
|
|
 |
|
 |
I tried this code on VB6 SP5:
Dim s As String
s = "12345"
MsgBox (IsNumeric(s))
and I didn't get the wrong "False" result, even changing Regional Options as described in the article. So, for the testing I did, it seems VB6 IsNumeric() function doesn't expose the problem VB.NET IsNumeric() function exposes.
Could you please post the VB6 code where you got the problem?
AV
|
|
|
|
 |
|
 |
In c# (and i believe VB is the same) couldn't you just :
bool isNumeric;
try
{
Convert.toInt64(text);
isNumeric = true;
}
catch
{
isNumeric = false;
}
In life truth does not matter. What really matters is what others believe to be the truth. (The Up and Comer - Book)
|
|
|
|
 |
|
 |
The problem is just again about efficiency: trapping an exception is not so lightweight, and if you have lots of data to validate then the Try/Catch approach could be not the best one (especially if much of them actually are not numeric).
AV
|
|
|
|
 |
|
 |
Oh.
You see, I'm a student studying programming so when I do this stuff I tend to ask 'isn't this better?' or 'isn't that quicker to write' so I love it when someone points out that what I was thinking was wrong -- this way I can learn more
thanks =)
In life truth does not matter. What really matters is what others believe to be the truth. (The Up and Comer - Book)
|
|
|
|
 |
|
 |
In general, don't use exceptions to perform functional programming. They are for handling things that you can't do anything about, or for "unexpected" circumstances. In this case, you are anticipating that sometimes the value could be non-numeric, and should program for it, not rely on an error to indicate that case.
Also, as the previous poster said, generating and catching exceptions is a lot of overhead.
Now, my opinion on this is, the whole point is moot. If someone goes and does something dumb (like setting the decimal and thousands seperator character to the same thing, they deserve to have things not work). If you plug your outlet strip into itself....don't blame the PC manufacturer because it won't turn on!
I would never bother to check this case, myself.
|
|
|
|
 |
|
 |
If I can agree with you about your sentence: "If someone goes and does something dumb, they deserve to have things not work", I disagree about the general "don't bother to check this" approach.
Think about this situation: you developed a software, then sold to many customers. What if they call your support because the application crashes? Okay, after reading this article, probably you would ask them to check their regional settings.
Anyway, your software immediately will seem "poor", because not "tolerant" to this issue.
Then, I think that people don't go every day on the Regional Settings panel, so, probably, when running an application, they are not all completely aware of the running settings, eventually modified by someone else! In this situation your application crash is something seen absolutely as due to the application itself.
AV
|
|
|
|
 |
|
 |
regular expression would not be a good alternative?
|
|
|
|
 |
|
 |
Sure: regular expressions are a good alternative.
|
|
|
|
 |
|
 |
I am converting a VB6 functions in a ASP.NET, and looked at replacing the IsNumeric, IsDate, InStr functions with
If (CompareValidator.CanConvert(TxtYear.Text.Trim, ValidationDataType.Integer))
If Not (CompareValidator.CanConvert(TxtSalary.Text.Trim, ValidationDataType.Decimal))
If (CompareValidator.CanConvert(TxtYear.Temperature.Trim, ValidationDataType.Double))
If (CompareValidator.CanConvert(TxtBirthDate.Text.Trim, ValidationDataType.Date))
If (TxtName.Text.Trim.IndexOf("DEMO") >= 0)
Only then, I can the parse the string value and convert it to a Int32, Decimal, Date, or whatever.
Some books suggest wrapping the Parse invokation inside a try block and catching the exception, but in my opinion, that is too expensive.
- alexis (romanaccio de roma)
|
|
|
|
 |
|
 |
Of course, this can be a solution if you're working on an ASP.NET web application. But probably it's not so suitable for other type of applications, being CanConvert() a method of the BaseCompareValidator class, that appears in the System.Web.UI.WebControls namespace.
AV
|
|
|
|
 |
|
 |
About wrapping the Parse() method in a Try/Catch block, see also the CodeProject article:
Performance Strategies for Enterprise Web Site Development[^]; I quote here a paragraph:
Using Exceptions to Control Process Flow
I'm not going to spend a lot of time going over exception handling, except to say that throwing exceptions are very costly for performance. You only want to use a try / catch block when you need to trap for an error. You never want to use it to control and direct the program’s process flow.
For example, I’ve seen this code used (and the .NET Framework actually uses this in its VB function IsNumeric):
public bool IsNumeric(string val)
{
try
{
int number = int.Parse(val);
return true;
}
catch
{
return false;
}
What if you have an XML block that has 50 values and you want to see if all 50 are numeric? If none of the values in the XML block are numeric, then you just threw 50 exceptions needlessly!
AV
|
|
|
|
 |
|
 |
Hi,
Here's a rather naive implementation of IsNumeric in c#. Support for fractional numbers should be easy to add:
public static bool IsNumeric(string str)
{
if (str==null || str.Length==0)
return false;
foreach(char c in str)
{
if (!Char.IsNumber(c))
{
return false;
}
}
return true;
}
|
|
|
|
 |
|
 |
With C# 2.0 it is even easier:
public static bool IsNumeric(string str)
{
Decimal dump;
return Decimal.TryParse(str,out dump)
}
It can be easily modified using int, float, double.
|
|
|
|
 |
|
 |
Cool code!
|
|
|
|
 |
|
 |
And it appears that this code is even faster than the native "IsNumeric"
|
|
|
|
 |
|
 |
Testing if a string is a number by testing chars separately is not safe;
according to MSDN, the IsNumber function returns True if the parameter is a char in these Unicode categories: DecimalDigitNumber, LetterNumber, or OtherNumber.
This means it returns true for V and X (which is the roman for 5 and 10), but false for "-.,".
Testing "15X7V" returns true, while "-12.5" returns false.
|
|
|
|
 |
|
 |
Yes, I think you're right! My solution is:
bool isNumeric = true;
try
{
decimal tmp = Convert.ToDecimal(someString);
}
catch
{
isNumeric = false;
}
-- modified at 20:14 Monday 19th December, 2005
|
|
|
|
 |
|
|
 |
|
 |
Yes, it uses the Double.TryParse() method, suggested also by mav.northwind (see the discussion thread "Better way IMO").
AV
|
|
|
|
 |
|
 |
Hi!
You already mentioned that the .NET framework offers more appropriate ways to check if a given string represents a number.
So instead of sticking with the old IsNumeric function and modifying the thread culture I think a better way would be to use Double.TryParse().
You can specify the culture info there and don't have to modify the current thread's culture.
Regards,
mav
|
|
|
|
 |
|
 |
That's true, thanks for your contribution.
For sure, better to use .NET "native" methods to do that stuff.
A friend of mine adopted the workaround I suggested just because he had tons of code already written, where he used also CDbl(), Clng(), etc.
AV
|
|
|
|
 |