Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln? (https://www.delphipraxis.net/104177-zeichenkette-pruefen-ob-gueltige-zahl-ohne-umwandeln.html)

Kenshin4455 28. Nov 2007 17:23


Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Ich hätte mal ne frage gibt es vielleicht in Delphi eine Funktion die man benutzen könnte um eine Zeichenkette zu Prüfen ohne sie umzuwandeln? und ohne das man jedes Zeichen einzeln durchsucht also mit einer Schleife?

"+242423423492849028042840928403284204832948204820 93482309483209480948903284098329084203823948092482 03"

aber nicht:

"-2734832748327482742374827482342842384724927498723ABA237428742837493274832749274987348723847294728372"

wegen den Zeichen dazwischen.

Dachte vielleicht geht das mit "in" also sprich if s in ['0'..'9'] aber das würde ja nur kucken ob die drin sind aber nich ob die aneinander hängen würden. Und ich weiß nicht wie ich alle Zeichen ausser 0..9 angeben könnnte.

Weil ich brauch eine Funktion die auch bei großen Zeichenketten erkennt ob es eine gültige Zahl ist ohne das ich gleich jedes Zeichen einzeln durchsuchen.

Wenns nich anders geht unterteile ich den String in mehrere Teile wo noch die Umwandlung in eine Extendet Zahl funktionieren würde sprich 20 stellen oder wieviel die fassen tut. Wäre dann zwar nicht Optimal aber noch in Ordnung.

thx

schonmal im vorraus

himitsu 28. Nov 2007 17:31

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Ja hallo ersmal und Willkommen und so :hi:

also in Delphi selber is nichts vorhanden,
aber wieso willst due denn nicht Stück für Stück prüfen?
Bsp:
Delphi-Quellcode:
B := True;
For i := 1 to Length(S) do
  If not ((S[i] in ['0'..'9'])
    or ((i = 1) and (S[i] in ['+', '-']))) Then B := False;

If B Then {istZahl}
PS: IN arbeitet nicht mit ganzen String, sondern nur mit ordinalen Typem wie z.B. einem einzelnem Zeichen(Char).


Alternativ könntes du natürlich auch nach etwas suchen, welches mit "großen" Zahlen zurechtkommen.
Hier im Forum suchenBigMath und Co.

Kenshin4455 28. Nov 2007 18:07

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
naja es geht eher darum das die zahl auch z.b 2^100 stellen haben könnte also unendlich lang sein kann da jedesmal alles durchgehen is fu find ich.... das schluckt doch bissel an der performance.

Hawkeye219 28. Nov 2007 18:33

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Hallo,

Zitat:

Zitat von Kenshin4455
[...]es geht eher darum das die zahl auch z.b 2^100 stellen haben könnte also unendlich lang sein kann[...]

die größten mir bekannten Festplatten haben eine Kapazität von 1 Terabyte (etwa 2^40 Byte). Wie und wo speicherst du Zahlen dieser Größenordnung und Genauigkeit für die Weiterverarbeitung?

Gruß Hawkeye

himitsu 28. Nov 2007 18:33

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Unendlich lang geht nicht (irgendwann geht dir der RAM für den String aus, wo dann ab 2^30 realistisch langsam Schluß ist :zwinker: )

Und wie sollte denn sonst geprüft werden?
(selbst wenn es eine Funktion dafür gäbe, dann würde die ähnlich arbeiten)

Zitat:

Zitat von Kenshin4455
das schluckt doch bissel an der performance.

Schlimmer wäre es wohl, wenn man den String zerlegt und versucht Stück für Stück (also sehr oft) in reelle Typen umzuwandeln.

alzaimar 28. Nov 2007 18:46

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Zitat:

Zitat von Kenshin4455
... das schluckt doch bissel an der performance.

Tipp: Erst testen, dann meckern.

Einfach mal die Zeit messen, die das Verfahren benötigt, um eine -sagen wir- Zahl mit 100.000.000 Stellen zu prüfen.
Wobei der Algo von himitsu noch nicht mal sonderlich performant ist, aber darum gings ihm hier sowieso nicht, nur um eine kurze und knappe Geschichte.

himitsu 28. Nov 2007 18:57

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
@alzaimar: OK, ein biss PChar, statt s[...], oder gleich 'ne nette ASM-Lösung, aber es ist schon mit Sicherheit viele tausend Mal schneller als z.B. 'ne Copy-StrToFloatDef-Variante :angel:

Der_Unwissende 28. Nov 2007 19:00

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Zitat:

Zitat von Hawkeye219
die größten mir bekannten Festplatten haben eine Kapazität von 1 Terabyte (etwa 2^40 Byte). Wie und wo speicherst du Zahlen dieser Größenordnung und Genauigkeit für die Weiterverarbeitung?

[Etwas OT]
Deshalb bin ich auch von Delphi.Win32 auf Delphi.DTM für Deterministische Turing Maschinen umgestiegen, macht die Sache gleich viel angenehmer :mrgreen:
[/Etwas OT]

LoCrux 29. Nov 2007 01:14

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Ok,

abgesehen von dem Speicherproblem :zwinker: mal ein Loesungsvorschlag.
hier sei ein Hoch auf die "Definitoere" der ASCII-Konvention. Tja, die Jungs haben sich noch was gedacht.

Ich definere einfach mal, dass (wie in deinem Beispiel) in dem "Zahlenstring" NUR ZIFFERN UND BUCHSTABEN
aber keine Sonderzeichen Vorkommen (<30h);
+ und - werden ignoriert, da als Vorzeichen immer an erster Position.;

Delphi-Quellcode:
// ADA. Quellcode-Tag zwecks Leerzeichenformatierung //

______Bit_76543210 
          ||||||||
0 = 30h = 00110000b
1 = 31h = 00110001b
.
.
9 = 39h = 00111001b

@ = 40h = 01000000b
A = 41h = 01000001b
.
.
' = 60h = 01100000b
a = 61h = 01100001b
.
.
usw.. Man richte jetzt sein Augenmerk auf Bit 6.
Zahlen:    Bit 6 = 0;
Buchstaben: Bit 6 = 1; Grossbuchstben: Bit 5 = 0;
                       Kleinbuchstaben Bit 5 = 1;
Damals war halt Rechenzeit knapp und Bit- & Boolesche-Operationen sind immer am schnellsten.
Du must also nicht deinen ganzen String duchlaufen. Definiere eine Bitmaske.

Delphi-Quellcode:
function NumStr(s:String):Boolean;
var
  i,l : Integer;
const
  mask = $40; // = 01000000b
begin
  result := true;
  i     := 1;
  l     := Length(s)+1;
  while (result and (i<l))
  do begin
    result := (mask and ORD(s[i]))<mask;
    inc(i);
  end;
end;
Und & Vergleichsoperationen:
Im besten Fall n=2 , im schlimmsten fall n=Length(s)*2 Operationen.

Reinhard Kern 29. Nov 2007 01:26

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Zitat:

Zitat von himitsu

Bsp:
Delphi-Quellcode:
B := True;
For i := 1 to Length(S) do
  If not ((S[i] in ['0'..'9'])
    or ((i = 1) and (S[i] in ['+', '-']))) Then B := False;

If B Then {istZahl}

Hallo,

das reicht so natürlich noch nicht - Nebenbedingungen sind z.B. dass + und - nur am Anfang auftreten dürfen und dass der String nur 1 Dezimalpunkt enthalten darf, von Exponentialdarstellungen mal abgesehen. Man muss sich also eine Zustandsmaschine schreiben, der man Zeichen für Zeichen übergibt.

Gruss Reinhard

Der_Unwissende 29. Nov 2007 08:39

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Zitat:

Zitat von LoCrux
Und & Vergleichsoperationen:
Im besten Fall n=2 , im schlimmsten fall n=Length(s)*2 Operationen.

Noch etwas besser wäre es imho, wenn man gleich mehrere Byte testet. Immerhin passt in ein Register auf den meisten CPUs schon mal mind. 32 Bit, entsprechend kann man auch eine Maske dieser Größe wählen und 4 Byte aufeinmal testen. Ändert natürlich nichts an der Asymptotischen Laufzeit, aber da käme ja auch das i-fache StrToInt in Frage.

Kenshin4455 29. Nov 2007 11:31

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Danke erstmal für die Vorschläge!!

Prinzipell gings nur darum das ich nich alles durchgehen wollt. Grund ist das die Daten für die Verarbeitung korrekt vorliegen müssen sprich eine durchgängige Zahl ohne Buchstaben Sonderzeichen etc. dazwischen. Ich könnte den Fehlerabfanng auch in die Verarbeitung mit reinbringen das nich das ding. Dachte nur vielleicht gibts da ne andere möglichkeit weil wäre schicker wenns vorher geschieht und er nich bei der verarbeitung merkt das es an vorletzter Stelle jetzt dann noch falsch ist. Dann hätte man sich ja die vorherigen Rechnungen sparen könnnen. Naja und das mit 2^100 war wohl bissel übertrieben gesagt aber ich meinte das auch nur darauf bezogen das die Zahlen die normalen Zahlen Integer etc. sprängen würden ich kenn jetzt BigMath nich was da oben mal gennant wurde link ging da auch nicht. Müste ich jetzt mal googeln.

Reinhard Kern 29. Nov 2007 12:38

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Zitat:

Zitat von Kenshin4455
Danke erstmal für die Vorschläge!!

Prinzipell gings nur darum das ich nich alles durchgehen wollt. Grund ist das die Daten für die Verarbeitung korrekt vorliegen müssen sprich eine durchgängige Zahl ohne Buchstaben Sonderzeichen etc. dazwischen. ....

Hallo,

dein Ansatz bedeutet, alle korrekten Zahlen werden komplett 2 x gelesen, nur die unkorrekten nur einmal. Wenn du nicht gerade davon ausgehst, dass die Mehrzahl fehlerhaft ist, bringt das keinen Vorteil, sondern dauert länger.

Gruss Reinhard

LoCrux 29. Nov 2007 12:57

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
@Der_Unwissende: LOGISCH! :zwinker: :roll:

Popov 29. Nov 2007 13:10

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Zitat:

Zitat von himitsu
Delphi-Quellcode:
B := True;
For i := 1 to Length(S) do
  If not ((S[i] in ['0'..'9'])
    or ((i = 1) and (S[i] in ['+', '-']))) Then B := False;

If B Then {istZahl}

Das ist nicht so gut, da hier unter Umständen unnötig die or ((i = 1) and (S[i] in ['+', '-'])) Überprüfung gemacht wird. Die Braucht man nur einmal, aber unter Umständen wird jedes Mal überprüft ob i = 1 ist usw. Also entweder es vor der Schleife machen oder die Compilerdirektive (ich glaube) {$B-} davorstellen, so daß nicht alles verglichen wird.

Außerdem kann der Nullterminierte String nicht maximal 2^32 (bzw. erst bei 64 Bit 2^64) sein?

@Kenshin4455

Auch wenn es ein IN gäbe, glaubst du Delphi würde das per Gedankenlesen rausfinden? Es wäre dann intern ohne eigene Routine, aber eine Überprüfung würde es trotzdem geben. Und bei 4 GB wären das paar Minuten.

himitsu 29. Nov 2007 17:13

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
@LoCrux:
es stimmt schon das wenn Bit 6 nicht gesetzt ist daß es eine Zahl sein könnte, aber es muß dennoch keine Zahl sein (ih weiße da nur mal auf die ganzen Steuerzeichen #0..#31 hin),
also einfach nur Bit 6 zu Prüfen reicht nicht aus.

@Reinhard Kern:
Zitat:

Nebenbedingungen sind z.B. dass + und - nur am Anfang auftreten dürfen
tut es doch :zwinker: ... siehe (i = 1)

@Popov: hast schon Recht (es funktioniert zwar, aber wenn die 2 Assembleranweisungen je durchgang für i=1 gesparrt würde, dann wär's schon etwas optimaler)

Und es wäre bestimmt nicht schlecht, wenn bei Auffinden eines unzuläßigen Zeichens die Schleife abgebrochen (siehe Break) würde :roll:
Delphi-Quellcode:
B := (S <> '') and (S[1] in ['+', '-', '0'..'9']);
For i := 2 to Length(S) do
  If not (S[i] in ['0'..'9']) Then Begin
    B := False;
    Break;
  End;

If B Then {istZahl}
ein Punkt war zwar nicht mit in der "Aufgabenstellung" zu erkennen, aber was soll's:
Delphi-Quellcode:
B := (S <> '') and (S[1] in ['+', '-', '0'..'9']);
B2 := True;
For i := 2 to Length(S) do
  If not (S[i] in ['0'..'9']) Then
    If B2 and (S[i] = '.') and (i < Length(S)
      and (S[i - 1] in ['0'..'9'])
      and (S[i + 1] in ['0'..'9']) Then
      B2 := False
    Else Begin
      B := False;
      Break;
    End;

If B Then {istZahl}
oder
Delphi-Quellcode:
B := (S <> '') and (S[1] in ['+', '-', '0'..'9']);
B2 := True;
For i := 2 to Length(S) do
  If not (S[i] in ['0'..'9']) Then
    If B2 and (S[i] = '.') and (i < Length(S))
      and ((i > 2) or (S[1] in ['0'..'9'])) Then
      B2 := False
    Else Begin
      B := False;
      Break;
    End;

If B Then {istZahl}
oder das vorherigge nochmal mit PChar
Delphi-Quellcode:
Var P: PChar;
  i, i2: Integer;
  B, B2: Boolean;
i2 := Length(S);
P := PChar(S);
B := (i2 <> 0) and (P^ in ['+', '-', '0'..'9']);
B2 := True;
For i := 2 to i2 do Begin
  Inc(P);
  If not (P^ in ['0'..'9']) Then
    If B2 and (P^ = '.') and (i < i2)
      and ((i > 2) or (S[1] in ['0'..'9'])) Then
      B2 := False
    Else Begin
      B := False;
      Break;
    End;
End;

If B Then {istZahl}
(ich hoffe letzteres stimmt ... hab's jetzt nur aus'm Kopf umgeschrieben und nicht getestet)

und hier nochmal die PChar-Variante ohne Punkt:
Delphi-Quellcode:
Var P: PChar;
  i, i2: Integer;
  B, B2: Boolean;
i2 := Length(S);
P := PChar(S);
B := (i2 <> 0) and (P^ in ['+', '-', '0'..'9']);
For i := 2 to i2 do Begin
  Inc(P);
  If not (P^ in ['0'..'9']) Then Begin
    B := False;
    Break;
  End;
End;

If B Then {istZahl}

alzaimar 29. Nov 2007 17:50

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
So wäre es mit einem Automaten (Es erkennt die Floatingpoint Notation, Fixed Point und Integer mit beliebig vielen Vorzeichen), also z.B.:
"+-+-+12345,3456453345345E-9123123123"

Delphi-Quellcode:
Function IsAnyNumber(Const aValue: String): Boolean;
Const
  map: Array[0..5, 1..6] Of Integer = (
  {0}(1, 2, -1, 0, -1, -1),
  {1}(1, 2, 4, -1, -1, 9),
  {2}(3, -1, -1, -1, -1, 9),
  {3}(3, -1, 4, 0, -1, 9),
  {4}(5, -1, -1, 4, -1, -1),
  {5}(5, -1, -1, -1, -1, 9)
    );

Var
  State, cChar, i: Integer;

Begin
  State := 0;
  Result := False;
  For i := 1 To Length(aValue) Do Begin
    Case aValue[i] Of
      '0'..'9': cChar := 1;
      ',', '.': cChar := 2;
      'E', 'e': cChar := 3;
      '-', '+': cChar := 4;
      Else     cChar := 5;
    End;
    State := map[State, cChar];
    If State = -1 Then Exit;
  End;
  If State <> 9 Then
    State := map[State, 6]; // Zustand bei Erkennen des Terminalsymbols

  Result := (State = 9)
End;

Popov 29. Nov 2007 18:07

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Zitat:

Zitat von alzaimar
Delphi-Quellcode:
Function IsAnyNumber(Const aValue: String): Boolean;

Schöne Funktion, nur sollte der Name mehr nach Float oder Realnumber klingen, denn Integer ist auch eine Nummer und kennt keine ".", ",", "E" in der Zahl.

Ansonsten ok.

alzaimar 29. Nov 2007 19:41

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Popov, die Funktion erkennt auch Ganzzahlen, eben alle Zahlen. Äh.. oder... eh.. :gruebel: Jedenfalls hat sie das eben noch.

LoCrux 30. Nov 2007 08:54

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
@himitsu

Zitat:

Zitat von himitsu
@LoCrux:
es stimmt schon das wenn Bit 6 nicht gesetzt ist daß es eine Zahl sein könnte, aber es muß dennoch keine Zahl sein (ih weiße da nur mal auf die ganzen Steuerzeichen #0..#31 hin),
also einfach nur Bit 6 zu Prüfen reicht nicht aus.

schaust DU...

Zitat:

Zitat von LoCrux
Ich definere einfach mal, dass (wie in deinem Beispiel) in dem "Zahlenstring" NUR ZIFFERN UND BUCHSTABEN
aber keine Sonderzeichen Vorkommen (<30h);
+ und - werden ignoriert, da als Vorzeichen immer an erster Position.;

@alzaimar

Coole Function. :cheers: :hello:

Amateurprofi 30. Nov 2007 11:41

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Na, dann will ich auch noch mal was beisteuern.
Dürfte um ca. 25 % schneller sein als optimale Pascal-Lösungen

Als gültig werden Strings erkannt, die
a) nur Ziffern enthalten, aber mindestens eine Ziffer
b) als erstes Zeichen ein Vorzeichen haben, dem mindestens eine Ziffer folgt

Delphi-Quellcode:
FUNCTION IsSignedInteger(s:string):boolean;
asm
            test eax,eax
            je   @Exit      // s=NIL
            cmp [eax-4],0 // geändert auf Wunsch des Erstellers
            je   @Fail      // s hat Länge 0
            mov  edx,eax
            mov  ax,[edx]   // AL=erstes Zeichen, AH=zweites Zeichen
            add  edx,2
            cmp  al,'-'
            je   @HasSign
            cmp  al,'+'
            jne  @NoSign
@HasSign:  add  ah,$D0
            sub  ah,$0A
            jb   @Loop      // Nach Sign folgt Ziffer
@Fail:     xor  eax,eax    // Fehler
            jmp  @Exit
@NoSign:   add  al,$D0
            sub  al,$0A
            jae  @Fail      // erstes Zeichen nicht '0'..'9','-','+'
            jmp  @Entry
@Loop:     mov  ax,[edx]
            add  edx,2
            add  al,$D0
            sub  al,$0A
            jae  @CheckEnd  // nicht '0'..'9'
@Entry:    add  ah,$D0
            sub  ah,$0A
            jb   @Loop      // ist '0'..'9'
            sub  ah,$D0-$0A
            je   @True      // Ist 0 Byte (Ende vom String)
@CheckEnd: sub  al,$D0-$0A
@True:     sete al
@Exit:
end;
[edit=MrSpock]3. ASM Befehl auf Wunsch des Erstellers geändert. Mfg, MrSpock[/edit]

himitsu 30. Nov 2007 19:08

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
@LoCrux: OK, wenn wirklich nur Zahlen und Buchstaben drin sind, dann sag ich nichts dagegen :angel:

LoCrux 30. Nov 2007 23:43

Re: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
@Amateurprofi:

SPEEDFREAK

:chat: :bouncing4: :bounce1: :bounce2: :bouncing4: :bounce1: :bounce2: :bouncing4: :bounce1: :bounce2: :bouncing4: :bounce1: :bounce2:

SvenLittkowski 7. Feb 2011 05:29

AW: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Und wie kann man testen ob ein String eine Zahl darstellt, wenn jene Zahlen auch negativ (mit vorangestelltem Minus) sein können und vom Typ Integer oder Real sein können (also mit Kommastellen, wobei das Komma je nach Land durch ein Komma oder einen Punkt dargestellt sein kann)? Gleichzeitig will ich aber Strings wie die nachfolgenden "Un"-Zahlen ausschließen:
- "12-3"
- "123-"
- "123."
- "1.2.3"
- "1-2-3"
- "-.-"

Bei meinem Problem kann ich mit Schleifen arbeiten. Nur der Algorithmus fällt mir nicht ein.

himitsu 7. Feb 2011 09:57

AW: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
Das Einfachste: Delphi-Referenz durchsuchenVal, Delphi-Referenz durchsuchenTryStrToInt, Delphi-Referenz durchsuchenTryStrToFloat, ...

Delphi-Referenz durchsuchenDecimalSeparator

Ansonsten einfach alles nacheinander prüfen und schauen, ob was Richtiges/Falsches drin vorkommt.
Delphi-Quellcode:
Result := False;
i := 1;
if (i <= Length(S)) and (S[i] in ['+', '-']) then
  Inc(i);
if (i > Length(S)) or not (S[i] in ['0'..'9']) then
  Exit;
while (i <= Length(S)) and (S[i] in ['0'..'9']) do
  Inc(i);
if (i <= Length(S)) and (S[i] = DecimalSeparator) then
begin
  Inc(i);
  if (i > Length(S)) or not (S[i] in ['0'..'9']) then
    Exit;
  while (i <= Length(S)) and (S[i] in ['0'..'9']) do
    Inc(i);
end;
Result := i > Length(S);
Das läßt sich natürlich noch ein bissl hübscher zusammenfassen.

DeddyH 7. Feb 2011 10:02

AW: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
http://www.delphipraxis.net/158131-t...tige-real.html

Deep-Sea 7. Feb 2011 10:02

AW: Zeichenkette Prüfen ob gültige Zahl ohne Umwandeln?
 
@himitsu & alle anderen:
Das Post von SvenLittkowski wurde von ihm auch in einem eigenen Thread gepostet, der unter dem Namen Test ob gültige REAL zu finden ist :-D

PS: Ach DeddyH ...... :p


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz