« The Xojo Storewide Sa… | Home | Thanksgiving Sale »

The IsNumeric function in Xojo

Today we had a discussion about the IsNumeric function. The developer expected it to take a string and return true or false depending on whether the value is a number. But let's take a deeper look on it as there may be some surprises.

First the IsNumeric function is documented to take a value, but the help doesn't tell the data type of that parameter. The latest Xojo IDE shows you the parameter and it is variant. Passing a string value will create a new variant object for the function call.

The function returns false for nil or variants containing structures or arrays. Otherwise it seems to query string value and loops over the character. If the text is NaN or Inf, the function will just return true.

ValueResult
Nilfalse
DateTime objectfalse
Datefalse
1.2true
1,2true
Textfalse
NaN as string or doubletrue
Inf as string or doubletrue
1.2afalse
Boolean valuefalse
Ptr valuetrue
Array of somethingfalse
Object like Windowfalse
1’2true in Switzerland

Now the 1.2 and 1,2 results as true depend on the current locale. For me in Germany the locale has comma as decimal separator and point as thousands separator. The function sees that beside digits those texts are used and returns true.

Now if your user is in Switzerland, the thousands separator is ’ character. The text "1’2" now returns true as it uses thousands separator. Decimal separator is the dot, but "1,2" still returns true, so dot and comma may be hard coded.

Since boolean values, Date and DateTime objects and Ptr values convert to strings with more than just digits, the function returns false. The Ptr has the &h as prefix, which causes the false result directly.

What consequences do you we take from this?

It may be possible to have a value, where IsNumeric returns true, but later Val, CDbl or more modern String.ToDouble returns 0 to report an error. If IsNumeric returns false, the text is most likely not a number. Since Val() and similar functions ignore following other characters like units, we my just pass a text to it and skip IsNumeric completely. IsNumeric returns false for something like "1.2cm", but val() reads it as 1.2 just fine.

We may in future not use IsNumeric at all since it seems to not be correct in cases, where we need it to be correct. So for text input, we may just call Val() or CDbl() functions and if result is zero, we check whether the text starts with zero or not. Or do our own function.

PS: String.ToDouble seems to just call CDbl() behind the scenes. Which my cause problems if someone develops some code to parse text files with US locale and then delivers to someone with a German locale.
21 11 22 - 11:58