Best way to check if a string is numeric?

Everything else that doesn't fall into one of the other PB categories.
miskox
User
User
Posts: 95
Joined: Sun Aug 27, 2017 7:37 pm
Location: Slovenia

Best way to check if a string is numeric?

Post by miskox »

What would be the best way to see if a string contains only numbers (numeric characters)?

Code: Select all

a.i=int (val ("123a"))
returns 123. I would like get 'notnumeric' or something.

Maybe this would do it?

Code: Select all

a$="123456adfasdf"
for n=0 to 9
     a$=RemoveString ( a$ , str (n) )
next n
if not a$=""
   debug ("not numeric")
endif

Saso
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Best way to check if a string is numeric?

Post by Dude »

Take your pick:

viewtopic.php?p=388044#p388044
viewtopic.php?f=12&t=16668&p=321136
viewtopic.php?f=12&t=45679
viewtopic.php?f=13&t=55169
etc

What I personally use:

Code: Select all

Procedure IsNumeric(num$)
  If CountString(num$,"+")<2 And CountString(num$,"-")<2 And CountString(num$,".")<2
    num$=RemoveString(num$," ")
    If num$
      ok=1
      l=Len(num$)
      For p=1 To l
        c=Asc(Mid(num$,p,1))
        If c>'/' And c<':' ; 0-9
          digits=1         ; Has at least one digit.
        ElseIf c<>'+' And c<>'-' And c<>'.'
          ok=0
          Break
        EndIf
      Next
      If digits=0
        ok=0
      EndIf
    EndIf
  EndIf
  ProcedureReturn ok
EndProcedure

Debug IsNumeric(" 913 ") ; Yes
Debug IsNumeric("3.14 ") ; Yes
Debug IsNumeric("-22.7") ; Yes
Debug IsNumeric(" +136") ; Yes
Debug IsNumeric("++136") ; No
Debug IsNumeric("12-No") ; No
Debug IsNumeric("-") ; No
Debug IsNumeric(".") ; No
Last edited by Dude on Tue Mar 12, 2019 12:08 pm, edited 1 time in total.
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Best way to check if a string is numeric?

Post by TI-994A »

miskox wrote:What would be the best way to see if a string contains only numbers (numeric characters)?
Not the best way; just another way:

Code: Select all

Procedure isNumeric(number.s)
  For i = 1 To Len(number)
    instr = Asc(Mid(number, i, 1))
    If instr < 48 Or instr > 57
      If instr <> 45 And instr <> 46
        notNumber = #True
        Break
      EndIf    
    EndIf
  Next i  
  ProcedureReturn (notNumber ! 1)
EndProcedure

If isNumeric("123")
  Debug "it's a number!"  
Else
  Debug "it's not a number!"
EndIf

If isNumeric("-123.123")
  Debug "it's a number!"  
Else
  Debug "it's not a number!"
EndIf

If isNumeric("123,abc")
  Debug "it's a number!"  
Else
  Debug "it's not a number!"
EndIf
Last edited by TI-994A on Tue Mar 12, 2019 12:54 pm, edited 1 time in total.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Best way to check if a string is numeric?

Post by Dude »

TI-994A wrote:Debug "it's a number!"
It's a sweater! ;)
User avatar
NicTheQuick
Addict
Addict
Posts: 1224
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Best way to check if a string is numeric?

Post by NicTheQuick »

If you only want to check against integers this should fit you needs:

Code: Select all

Prototype.i strfunc(a.s)

Procedure.i _isInt(*a.Character)
	; Accept + or - in the beginning
	If *a\c = '+' Or *a\c = '-'
		*a + SizeOf(Character)
	EndIf

	; Don't allow empty strings
	If *a\c = 0
		ProcedureReturn #False
	EndIf
	
	; Accept only 0 to 9
	While *a\c
		If *a\c < '0' Or *a\c > '9'
			ProcedureReturn #False
		EndIf
		*a + SizeOf(Character)
	Wend
	ProcedureReturn #True
EndProcedure

Global isInt.strfunc = @_isInt()

Debug isInt("123")
Debug isInt("123v")
Debug isInt("+123")
Debug isInt("-0")
Debug isInt("")
Debug isInt("+")
The prototype is only there to avoid copying the given string before calling the procedure but at the same time don't bother you with the @.
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.
User avatar
blueb
Addict
Addict
Posts: 1041
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: Best way to check if a string is numeric?

Post by blueb »

miskox wrote:... What would be the best way to see if a string contains only numbers (numeric characters)?

Saso
Probably, you'll want to allow for Scientific notation.. e.g. "1.7e-21".

The code I use is from Stargate back in December 2014

Code: Select all

Procedure.i IsNumeric(St.s) ; Stargate December 2014
     EnableExplicit
     Structure CharacterArray
            StructureUnion
              c.c[0]
            EndStructureUnion
       EndStructure
       
  Protected *String.CharacterArray=@St
  Protected Cnt.i,Length.i=Len(St.s)
  Protected Pt.i,e.i
  Select *String\c[0]
    Case '+', '-' :Cnt=1:
    Case '.'          :Cnt=1:Pt=#True
  EndSelect:If Length=Cnt:ProcedureReturn #False:EndIf
  Repeat
    Select *String\c[Cnt]
      Case '0' To '9' :Cnt+1:Continue
      Case '.'             :If Pt:ProcedureReturn #False:Else:Pt=#True:Cnt+1:Continue:EndIf
      Case 'e','E'    
        If e
          ProcedureReturn #False
        Else
          Cnt+1:Select *String\c[Cnt]
            Case '+','-','0' To '9':e=#True:Cnt+1
            Default:ProcedureReturn #False
          EndSelect
        EndIf
      Default:ProcedureReturn #False
    EndSelect
  Until Length=Cnt:ProcedureReturn #True
EndProcedure

Debug "Numeric"
Debug IsNumeric("123")
Debug IsNumeric("17.3")
Debug IsNumeric("-14.8")
Debug IsNumeric(".67")
Debug IsNumeric("45e11")
Debug IsNumeric("1.7e-6")
Debug IsNumeric("1.1")
Debug ""
Debug "Not Numeric"
Debug IsNumeric("45Alpha")
Debug IsNumeric("1...2...3...More")
Debug IsNumeric("PureBasic")
- It was too lonely at the top.

System : PB 6.10 Beta 9 (x64) and Win Pro 11 (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
miskox
User
User
Posts: 95
Joined: Sun Aug 27, 2017 7:37 pm
Location: Slovenia

Re: Best way to check if a string is numeric?

Post by miskox »

Wow! So many approaches. This just calls for a system function to be created (with some additional flags which would determine what to look for (only numbers, signs (+,-...)...).

Looks like everybody needs to use the one that is best for each specific task.

Saso
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Best way to check if a string is numeric?

Post by #NULL »

For integers you might just convert it to int, then back to string and compare it.
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Best way to check if a string is numeric?

Post by skywalk »

I use this to determine type of numeric, if any.

Code: Select all

Procedure.i SF_IsNumeric(StrIn$, DecimalCharacter.c='.', ThousandsSeparator.c=',')
  ; REV:  100405, skywalk
  ;       Modified from Xombie(061129) + Demivec(100323)
  ;       Removed 3 constants, add Lcase, add 'd' exponent support
  ;       Enabled leading '.' to define a numeric: -.1 = -0.1
  ;       Allow trailing text characters to match Val|D() behavior.
  ;       Dropped LCase() operation.
  ; Return: 0 = non-numeric value = 0
  ;         1 = positive integer
  ;        -1 = negative integer
  ;         2 = positive float
  ;        -2 = negative float
  StrIn$ = Trim(StrIn$)
  Protected.i IsDecimal, CaughtThousand, CaughtDecimal, CaughtE
  Protected.i IsSignPresent, IsSignAllowed = 1, Sgn = 1
  Protected.i CountNumeric
  Protected.i *CurrentChar.Character = @StrIn$
  While *CurrentChar\c
    Select *CurrentChar\c
    Case '0' To '9'
      CountNumeric + 1
      If CaughtThousand And CountNumeric > 3
        ProcedureReturn 0
      EndIf
      IsSignAllowed = 0
    Case ThousandsSeparator
      If CaughtDecimal Or CaughtE Or (CountNumeric = 0) Or (CaughtThousand And CountNumeric <> 3)
        ProcedureReturn 0
      EndIf
      CaughtThousand = 1
      CountNumeric = 0
    Case DecimalCharacter
      ;If CaughtDecimal Or CaughtE Or CountNumeric = 0 Or (CaughtThousand And CountNumeric <> 3)
      If CaughtDecimal Or CaughtE Or (CaughtThousand And CountNumeric <> 3)
        ; Allow leading decimal to signify a numeric
        ProcedureReturn 0
      EndIf
      CountNumeric = 0
      CaughtDecimal = 1
      IsDecimal = 1
      CaughtThousand = 0
    Case '-'
      If IsSignPresent Or Not IsSignAllowed
        ProcedureReturn 0
      EndIf 
      If Not CaughtE: Sgn = -1: EndIf
      IsSignPresent = 1
    Case '+'
      If IsSignPresent Or Not IsSignAllowed
        ProcedureReturn 0
      EndIf 
      IsSignPresent = 1
    Case 'E', 'e', 'D', 'd'
      If CaughtE Or (CountNumeric = 0) Or (CaughtThousand And CountNumeric <> 3)
        ProcedureReturn 0
      EndIf
      CaughtE = 1
      CountNumeric = 0
      CaughtDecimal = 0
      CaughtThousand = 0
      IsSignPresent = 0
      IsSignAllowed = 1
    Default
      If CountNumeric   ; Allow trailing text characters to match Val|D() behavior.
        Break
      Else
        ProcedureReturn 0
      EndIf
    EndSelect
    ;Debug PeekS(@*CurrentChar\c, 1)
    *CurrentChar + SizeOf(Character)
  Wend
  If CountNumeric = 0 Or (CaughtThousand And CountNumeric <> 3)
    ProcedureReturn 0
  EndIf
  If IsDecimal
    ProcedureReturn 2 * Sgn ; -> Float
  EndIf
  ProcedureReturn Sgn       ; -> Integer
EndProcedure
CompilerIf 1
  ; Val() ignores trailing string data: Debug Val("34  HELLO")
  ;Debug Val("34  HELLO")
  ;Debug ValD("34.4e4  HELLO")
  Debug ";SF_IsNumeric('34  HELLO')         = " + SF_IsNumeric("34  HELLO")
  ;CallDebugger
  Debug ";SF_IsNumeric('  034  HELLO')      = " + SF_IsNumeric("  034  HELLO")
  Debug ";SF_IsNumeric('  +034  HELLO')     = " + SF_IsNumeric("  +034  HELLO")
  Debug ";SF_IsNumeric('  +034.55e-5  HELLO') = " + SF_IsNumeric("  +034.55e-5  HELLO")
  Debug ";SF_IsNumeric('  +034.55e-5HELLO') = " + SF_IsNumeric("  +034.55e-5HELLO")
  Debug ";SF_IsNumeric('  hello+034.55e-5') = " + SF_IsNumeric("  hello+034.55e-5")
  Debug ";SF_IsNumeric('  +034.55E-5')      = " + SF_IsNumeric("  +034.55E-5")
  Debug ";SF_IsNumeric('  +034.55e-5')      = " + SF_IsNumeric("  +034.55e-5")
  Debug ";SF_IsNumeric('  10,00')           = " + SF_IsNumeric("  10,00")
  Debug ";SF_IsNumeric('  10,000')          = " + SF_IsNumeric("  10,000")
  Debug ";SF_IsNumeric('  10.00')           = " + SF_IsNumeric("  10.00")
  Debug ";SF_IsNumeric('-  10.00')          = " + SF_IsNumeric("-  10.00")
  Debug ";SF_IsNumeric(' -10.00')           = " + SF_IsNumeric(" -10.00")
  Debug ";SF_IsNumeric(' -1000')            = " + SF_IsNumeric(" -1000")
  Debug ";SF_IsNumeric('  +034.55e-5555')   = " + SF_IsNumeric("  +034.55e-5555")
  Debug ";SF_IsNumeric('  +034.55e-AB')     = " + SF_IsNumeric("  +034.55e-AB")
  Debug ";SF_IsNumeric('  +034.55e- AB')    = " + SF_IsNumeric("  +034.55e- AB")
  Debug ";SF_IsNumeric('1..2..3..')         = " + SF_IsNumeric("1..2..3..")
CompilerEndIf
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Zebuddi123
Enthusiast
Enthusiast
Posts: 794
Joined: Wed Feb 01, 2012 3:30 pm
Location: Nottinghamshire UK
Contact:

Re: Best way to check if a string is numeric?

Post by Zebuddi123 »

Hi Moskox

zebuddi :)

Code: Select all

Procedure.b IsNumeric(string.s) ;Returns 1 if numeric else 0 for any non numeric values
	Protected iRegex = CreateRegularExpression(#PB_Any, "\D"),bParam = Bool(Not MatchRegularExpression(iRegex, string))
	FreeRegularExpression(iRegex)
	ProcedureReturn bParam
EndProcedure
malleo, caput, bang. Ego, comprehendunt in tempore
Post Reply