IsNumber() Function #5326262 :)
Posted: Wed Oct 26, 2005 8:18 pm
Code updated For 5.20+
My own IsNumber function to add to everyone else's. I'm using it for my xGrid project and thought it might be useful to someone. Maybe
It has multiple returns. 1 signifies a positive integer, -1 a negative integer. 2 signifies a positive float, -2 a negative float. 0 signifies False - non-numeric. I can't remember but for some reason I thought someone else's IsNumber/IsNumeric did a similar return.
Although I have a part for hex, it's not really active. The function will test for thousands separators and decimals in strings. Optionally, you can pass the address to a string and the function will return a 'cleaned' version of the number. For example - "2,135.626" will be returned as "2135.626".
I tried to add useful comments for people to see what's happening. Not sure on the speed but it should be okay for a non-ASM function. Let me know if you spot bugs or just want to say hey ^_^
My own IsNumber function to add to everyone else's. I'm using it for my xGrid project and thought it might be useful to someone. Maybe

Although I have a part for hex, it's not really active. The function will test for thousands separators and decimals in strings. Optionally, you can pass the address to a string and the function will return a 'cleaned' version of the number. For example - "2,135.626" will be returned as "2135.626".
Code: Select all
Procedure IsNumber(inString.s, DecimalCharacter.b, ThousandsSeparator.b, *ReturnValue)
; TODO: Update to test for international decimal value and then check for IsNumeric calls to make sure they are
; international ready. Maybe need a StringToSingle call first?
;
; *ReturnValue (if a LONG address is passed) will contain a 'cleaned' version of the number. eg, no commas.
; IT MUST BE INITIALZED TO EMPTY OR OTHERWISE OR ELSE NOTHING WILL BE PASSED BACK.
;
;
HoldCleaned.s
; String used to hold the 'cleaned' value.
; The count of the decimal/thousands separator. Also the count of the numbers.
isHex.b = #False
;
; The location of the decimal/thousands separator.
IsNegative.b
; True if the value is negative.
HoldChar.b
; This will store an individual character to test if it's numeric.
*MemPosition = @inString
;
HoldLength = Len(inString)
; This will store the length of our string in characters.
Repeat
;
HoldChar = PeekB(*MemPosition)
; Store the current character.
If HoldChar > 47 And HoldChar < 58
; Numeral 0 to 9.
If CountDecimal : CountDecimalNumerics + 1 : Else : CountNumeric + 1 : EndIf
;
HoldCleaned + PeekS(*MemPosition, 1)
; Add the number to the 'clean' string.
ElseIf HoldChar = 45
; - (negative sign)
If iLoop > 0 : ProcedureReturn #False : EndIf
;
IsNegative = #True
; If the minus sign is not at the front, it's not a numeral.
HoldCleaned + PeekS(*MemPosition, 1)
; Add the negative sign to the 'clean' string.
ElseIf HoldChar = 36
; $ (hex sign)
If iLoop > 0 : ProcedureReturn #False : EndIf
; If the $ isn't at the front of the string, it's not a hex value.
isHex = #True
;
ElseIf HoldChar = ThousandsSeparator ; 44
; , (comma)
If CountDecimal Or isHex : ProcedureReturn #False : EndIf
; Never thousands after a decimal. Also, hex values never use a comma.
If CountThousands And CountNumeric < 3 : ProcedureReturn #False : EndIf
; Thousands separator requires at least three numbers.
CountNumeric = 0
; Reset the number count.
CountThousands + 1
;
ElseIf HoldChar = DecimalCharacter ; 46
; . (decimal sign)
If CountDecimal > 1 : ProcedureReturn #False : EndIf
; If there is more than one decimal, it's not an integer.
If isHex : ProcedureReturn #False : EndIf
; A hexidecimal will never have a decimal.
If CountThousands And CountNumeric < 3 : ProcedureReturn #False : EndIf
; Thousands separator requires at least three numbers.
PositionDecimal = *MemPosition - @inString
; Store the location of the decimal character.
CountDecimal + 1
; Increment our decimal count.
HoldCleaned + PeekS(*MemPosition, 1)
; Add the decimal to the 'clean' string.
Else
;
ProcedureReturn #False
; Unknown character, non-numeral.
EndIf
;
*MemPosition + 1
;
Until *MemPosition - @inString = HoldLength
;
If CountThousands And CountNumeric < 3 : ProcedureReturn #False : EndIf
; Thousands separator requires at least three numbers.
If CountDecimal And CountDecimalNumerics
;
If *ReturnValue : PokeS(*ReturnValue, HoldCleaned) : EndIf
; Return a 'cleaned' float value.
If IsNegative : ProcedureReturn -2 : Else : ProcedureReturn 2 : EndIf
; Return 2 for a float or -2 for a negative float. There must be numbers after the decimal to be considered a float.
EndIf
;
If CountNumeric
;
If *ReturnValue : PokeS(*ReturnValue, HoldCleaned) : EndIf
; Return a 'cleaned' integer value.
If IsNegative : ProcedureReturn -1 : Else : ProcedureReturn 1 : EndIf
; Return -1 for a negative integer or 1 for a positive integer.
EndIf
;
ProcedureReturn #False
; If we got this far, it must be a string.
EndProcedure