Seite 2 von 3
Re: isNumeric
Verfasst: 24.01.2015 19:21
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:
Und
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.)
Re: isNumeric
Verfasst: 24.01.2015 20:17
von NicTheQuick
@Nino:
Deine Funktion ist auch nicht unschlagbar, wenn man nur genug Nachkommastellen dazu nimmt.
Allerdings wäre sogar noch eine Stelle mehr mit Doubles darstellbar:
Re: isNumeric
Verfasst: 24.01.2015 20:41
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.
Re: isNumeric
Verfasst: 24.01.2015 21:00
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
das hier machen:
Re: isNumeric
Verfasst: 24.01.2015 21:26
von Nino
Sieht gut aus, und funktioniert hier einwandfrei.
Re: isNumeric
Verfasst: 24.01.2015 22:00
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.
Re: isNumeric
Verfasst: 25.01.2015 00:20
von Vera
Tolle Beispiele ~ danke
Scharf find' ich die RegEx-Variante.
Frage: Wo findet man, welche Anteile der Rex-Ex-Ausdrücke PB-Syntax sind?
Re: isNumeric
Verfasst: 25.01.2015 00:30
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.
Re: isNumeric
Verfasst: 25.01.2015 00:32
von Tommy
RegEx Variante finde ich auch am besten
aber unbedingt Lizenzbdingung beachten! Man muss glaube ich den Entwickler in seiner About nennen.
Re: isNumeric
Verfasst: 25.01.2015 00:45
von Nino
Besser nicht glauben oder raten, sondern
lesen.