isNumeric (alle OS, Anfänger-Tip)

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: isNumeric

Beitrag von Nino »

NicTheQuick hat geschrieben:Das Problem ist, dass du den Trick von Nino mit dem + "1" wieder raus genommen hast.
Der hatte nämlich verhindert, dass das hier funktioniert:

Code: Alles auswählen

Debug isNumeric("3a") ;ergibt 1
Und

Code: Alles auswählen

Debug isNumeric("0.0")
ergibt mit Tommys letztem Code fälschlicherweise 0.

In meinem Macro hat hingegen bisher noch niemand einen Fehler gefunden. :-)
(Und wer unbedingt will, kann ja das ReplaceString()-Gedöns davor schreiben.)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: isNumeric

Beitrag von NicTheQuick »

@Nino:
Deine Funktion ist auch nicht unschlagbar, wenn man nur genug Nachkommastellen dazu nimmt. ;)

Code: Alles auswählen

Debug IsNumeric("1.234567890123456") ; -> 0
Allerdings wäre sogar noch eine Stelle mehr mit Doubles darstellbar:

Code: Alles auswählen

d.d = 1.2345678901234567
Debug StrD(d, 16)
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: isNumeric

Beitrag von Nino »

@NicTheQuick:
Vielen Dank, dass Du diesen Bug gefunden hast.

Ich habe jetzt ein ValD() durch ValF() ersetzt, und das andere ValD() stehen gelassen.
Nun funktioniert auch Dein Beispiel. :-)
Aber evtl. wird sich wieder ein anderes Beispiel finden lassen, wo's nicht funktioniert.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: isNumeric

Beitrag von NicTheQuick »

Und da wir schon dabei sind. Ich habe mich jetzt auch dazu hinreißen lassen etwas herum zu pointern. Ich hoffe ich habe an alles gedacht:

Code: Alles auswählen

Procedure.i isNumeric(value.s)
	Protected *c.Character = @value
	
	;Skip whitespaces
	While *c\c = ' ' Or *c\c = 9
		*c + SizeOf(Character)
	Wend
	
	;Skip Minus and Plus signs
	Protected i.i = 0
	While *c\c = '-' Or *c\c = '+'
		*c + SizeOf(Character)
		i + 1
	Wend
	If (i > 1) ; Error if more than one sign
		ProcedureReturn #False
	EndIf
	i = 0	
	
	Select *c\c
		Case '$'	; Hex
			Repeat
				i + 1
				*c + SizeOf(Character)
			Until Not ((*c\c >= '0' And *c\c <= '9') Or (*c\c >= 'a' And *c\c <= 'f') Or (*c\c >= 'A' And *c\c <= 'F'))
			i - 1
			
		Case '%'	; Binary
			Repeat
				i + 1
				*c + SizeOf(Character)
			Until *c\c <> '0' And *c\c <> '1'
			i - 1
			
		Case '0' To '9'	; Decimal
			Protected j = 0
			Repeat
				i + 1
				If (*c\c = '.')
					If (j = 1)	;Too many commas
						ProcedureReturn #False
					EndIf
					j + 1
				EndIf
				*c + SizeOf(Character)
			Until (*c\c < '0' Or *c\c > '9') And *c\c <> '.'
			
			If (i - j = 0) ; No digits
				ProcedureReturn #False
			EndIf
			
			If (*c\c = 'e' Or *c\c = 'E')	;Exponent
				*c + SizeOf(Character)
				
				;Skip Minus and Plus signs
				i = 0
				While *c\c = '-' Or *c\c = '+'
					*c + SizeOf(Character)
					i + 1
				Wend
				If (i > 1) ; Error if more than one sign
					ProcedureReturn #False
				EndIf
				
				While (*c\c >= '0' And *c\c <= '9')
					*c + SizeOf(Character)
					i + 1
				Wend
			EndIf
			
		Default
			ProcedureReturn #False
	EndSelect
	
	While *c\c = ' ' Or *c\c = 9
		*c + SizeOf(Character)
	Wend
	ProcedureReturn Bool(i And *c\c = 0)
EndProcedure

; ===  Test  ===
Debug "=== Numeric ==="
Debug IsNumeric("123")
Debug IsNumeric("1.23")
Debug IsNumeric("-1.234567890123456")
Debug IsNumeric("$FF")
Debug IsNumeric("-%101  ")
Debug IsNumeric("+1.7e-6")
Debug IsNumeric("0")
Debug IsNumeric("  -0.0")

Debug "=== Not Numeric ==="
Debug isNumeric("--12")
Debug isNumeric("12.45.6")
Debug isNumeric("%")
Debug isNumeric("$g")
Debug IsNumeric("12c")
Debug IsNumeric("12c")
Debug IsNumeric("abc")
Debug IsNumeric("")
'ValD()' akzeptiert übrigens auch Dezimalzahlen ohne Ziffern vor dem Komma. Falls das auch hier gewünscht ist, muss man lediglich aus

Code: Alles auswählen

Case '0' To '9'
das hier machen:

Code: Alles auswählen

Case '0' To '9', '.'
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: isNumeric

Beitrag von Nino »

Sieht gut aus, und funktioniert hier einwandfrei.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: isNumeric

Beitrag von NicTheQuick »

Hier noch die RegEx-Variante, die genau das gleiche macht wie meine Pointervariante.

Code: Alles auswählen

Procedure.i IsNumeric(value.s)
	Static regex.i = 0
	If regex = 0
		;regex = CreateRegularExpression(#PB_Any, "^\s*(\+|-)?(\$[0-9a-fA-F]+|%[01]+|([0-9]+|[0-9]*\.[0-9]+)([eE](\+|-)?[0-9]+)?)\s*$", #PB_RegularExpression_MultiLine)
		regex = CreateRegularExpression(#PB_Any, "^\s*(\+|-)?(\$[[:xdigit:]]+|%[01]+|(\d+|\d*\.\d+)([eE](\+|-)?\d+)?)\s*$", #PB_RegularExpression_MultiLine)
	EndIf
	ProcedureReturn MatchRegularExpression(regex, value)
EndProcedure

; ===  Test  ===
Debug "=== Numeric ==="
Debug IsNumeric("123")
Debug IsNumeric("1.23")
Debug IsNumeric("-1.234567890123456")
Debug IsNumeric("$FF")
Debug IsNumeric("-%101  ")
Debug IsNumeric("+1.7e-6")
Debug IsNumeric("0")
Debug IsNumeric("  -0.0")
Debug isNumeric(".123")

Debug "=== Not Numeric ==="
Debug isNumeric("--12")
Debug isNumeric("12.45.6")
Debug isNumeric("%")
Debug isNumeric("$g")
Debug IsNumeric("12c")
Debug IsNumeric("12c")
Debug IsNumeric("abc")
Debug IsNumeric("")
Debug IsNumeric("e14")
Edit: Ein paar Zeichen durch ihre Zeichenklasse ersetzt.
Benutzeravatar
Vera
Beiträge: 928
Registriert: 18.03.2009 14:47
Computerausstattung: Win XP SP2, Suse 11.1
Wohnort: Essen

Re: isNumeric

Beitrag von Vera »

Tolle Beispiele ~ danke :D

Scharf find' ich die RegEx-Variante.

Frage: Wo findet man, welche Anteile der Rex-Ex-Ausdrücke PB-Syntax sind?
°
<°)))o><
~~~~~~~~~
echo "Don't worry"
echo "Keep quiet"
@echo off
format forum:\
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: isNumeric

Beitrag von NicTheQuick »

Vera hat geschrieben:Frage: Wo findet man, welche Anteile der Rex-Ex-Ausdrücke PB-Syntax sind?
Was meinst du damit? RegEx ist RegEx. Das hat nichts mit PB zu tun. Außer, dass man da RegEx eben nutzen kann. Alles weitere findest du bei Wiki - Regulärer Ausdruck.
Benutzeravatar
Tommy
Spassvogel
Beiträge: 319
Registriert: 17.10.2013 14:36

Re: isNumeric

Beitrag von Tommy »

RegEx Variante finde ich auch am besten
aber unbedingt Lizenzbdingung beachten! Man muss glaube ich den Entwickler in seiner About nennen.
Zuletzt geändert von Tommy am 26.01.2015 14:51, insgesamt 1-mal geändert.
PB 5.41 x64
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: isNumeric

Beitrag von Nino »

Besser nicht glauben oder raten, sondern lesen.
Antworten