EnableExplicit
;Yet another IsNumeric() function!
;Author: Mijikai
Procedure.b IsNumeric(*c.Character,d.i)
Static.s p
Static.Character *p
Protected.Character *m
Protected.i e,t,l
p = "0123456789.-"
*p = @p
*m = *p
If *c
If *c\c <> 0 And *c\c <> '.'
If *c\c = '-'
*c + 2
If *c\c <> 0 And *c\c <> '.'
e = '-'
EndIf
Else
e = '-'
EndIf
If e
If d = 0
e = '.'
EndIf
While *c\c <> 0
While *m\c <> e
If *m\c = *c\c
If *m\c = '.'
e = '.'
EndIf
t + 1
Break
EndIf
*m + 2
Wend
*m = *p
*c + 2
l + 1
Wend
*c - 2
If t = l And *c\c <> '.'
ProcedureReturn #True
EndIf
EndIf
EndIf
EndIf
ProcedureReturn #False
EndProcedure
Procedure.i main();Example
Protected.s a,b
a = "-10";<- numbers can be positive or negativ
b = "1.0";<- optionally it can be a number with a dot '.'
Debug IsNumeric(@a,0);<- just a number no other symbols expected
Debug IsNumeric(@b,1);<- set d to 1 if the number may contain a '.'
;Note:
;- No support for ',' instead of '.' (usually we use '.' for floats/doubles)
;- No support for notation ex. 'e-20'
EndProcedure
End main()
Last edited by Mijikai on Wed Jun 04, 2025 11:51 pm, edited 3 times in total.
Instead of using static variables you may just use a data section with the characters. Since labels are only valid in the local scope of a procedure this will not interfere with labels of the same name in other places.
Also the return type of `.b` is bad because it adds unnecessary low level type casting on modern 64 bit systems. Just use a `.i` there.
Please use meaningful variable names that can help future programmers understand your code better.
Instead of just adding 2 when iterating through the string, better use SizeOf(Character). I know that Purebasic nowadays only uses Unicode but this is also a helpful information for other coders to understand better what you are doing. It will not add any delay because the compiler replaces it with a 2 before compiling anyway.
The procedure will not recognize floating point values in the scientific format like 1.0e-5.
And last but not least: With some prototype magic you can get rid of the @ when calling the procedure.
Here is the code how I would write it, except for the meaningful variable names and the scientific format.
EnableExplicit
;Yet another IsNumeric() function!
;Author: Mijikai
Procedure.i _IsNumeric(*c.Character, d.i)
Debug *c
Protected.Character *m
Protected.i e, t, l
*m = ?number_characters
If *c
If *c\c <> 0 And *c\c <> '.'
If *c\c = '-'
*c + SizeOf(Character)
If *c\c <> 0 And *c\c <> '.'
e = '-'
EndIf
Else
e = '-'
EndIf
If e
If d = 0
e = '.'
EndIf
While *c\c <> 0
While *m\c <> e
If *m\c = *c\c
If *m\c = '.'
e = '.'
EndIf
t + 1
Break
EndIf
*m + SizeOf(Character)
Wend
*m = ?number_characters
*c + SizeOf(Character)
l + 1
Wend
*c - SizeOf(Character)
If t = l And *c\c <> '.'
ProcedureReturn #True
EndIf
EndIf
EndIf
EndIf
ProcedureReturn #False
DataSection
number_characters:
Data.s "0123456789.-"
EndDataSection
EndProcedure
; Use the prototype to always handover the string by reference
Prototype isNumericParams(text.p-Unicode, flags.i)
; Define the procedure in the global space with the right name
Global isNumeric.isNumericParams = @_IsNumeric()
Procedure.i main();Example
Protected.s a,b
a = "-10";<- numbers can be positive or negativ
b = "1.0";<- optionally it can be a number with a dot '.'
Debug @a
Debug IsNumeric(a, 0);<- just a number no other symbols expected
Debug @b
Debug IsNumeric(b, 1);<- set d to 1 if the number may contain a '.'
;Note:
;- No support for ',' instead of '.' (usually we use '.' for floats/doubles)
;- No support for notation ex. 'e-20'
EndProcedure
End main()
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
NicTheQuick wrote: Wed Jun 04, 2025 9:01 pm
Here some feedback
Thanks for the feedback @NickTheQuick
Update 1
I hope the code is more readable now, i also added support for 1.0e-5 notation.
It still uses Static because its totally fine, i also did not add the Prototype for clarity.