Peter: ctype-digit

Hi,

ich bin heute zufällig auf die Ctype Funktionen gestossen. Nicht schlecht dachte ich und wundernswert, warum bei den typischen Fragen zu Formularüberprüfungen selten, ich hatte es noch nie gesehen, empfohlen wurde.

Nach ein wenig Nachforschung, fand ich den Hauptgrund darin, weil zb. Ctype Funktionen ctype_digit() nur mit Strings zurecht kommt:
http://forum.de.selfhtml.org/archiv/2008/4/t170491/#m1114558

Na gut, dachte ich wär ja auch zu schön gewesen, was soll ich mich also damit rumärgern, bleibe ich doch gleich bei is_int oder is_numeric, auch wenn ich da einiges anpassen muss, den das problem ist ja:

1. Kommt eine (scheinbare) Zahl an oder ist es doch ein String, der aussieht wie eine Zahl? Was ein Problem bei is_int sein könnte

2. 2.455 oder 2,44 sind auch Zahlen, ok kein integer aber somit geht is_numeric schon mal nicht, wenn ich nur Integer akzeptieren will.

Bei ctype_digit müsste ich auch erst sicherheitshalber in String konvertieren, damit die Funktion fehlerfrei arbeitet. Und auch dachte ich, wird ja vielleicht noch einen Grund haben, warum Ctype Funktionen so selten erwähnt werden, da las ich das und vor allen der Geschwindigkeitsvorteil war interessant:

http://forum.de.selfhtml.org/archiv/2005/8/t113304/#m719370

Also auch noch schneller als die anderen, hmmm. Deshalb jetzt mal eine konkrete Frage:

Es dürfe Zahlen von 0-unendlich eingegeben werden. Allerdings keine Floatwerte oder sonst irgendwelche nichtnumerischen Zeichen. Die Werte können intern erzeugt werden, aber auch von einem Formular kommen.

Somit:

1243  = true
32329 = true
0     = true
348598584305984084300458045983 = true
454,254 = false
113213.34 = false
32j3h8trt = false
1232+342 = false
2124%444 = false
1 = true

Welche Funktion(unter Berücksichtigung der notwendigen Anpasssung des Werte an die Funktion)sollte ich nun, und warum, dafür nutzen?

Oder doch besser $pattern = '/\d*/';?

Peter

ps. Kann mal Jemand sagen warum hier oft noch unzählige Zeilenumbrüche vorhanden sin, oder bzw, ist es egal werden die beim Post automatisch gelöscht? Ach ich probiers mal aus, wenns nicht gelöscht wird, müsste jetzt ne ganze Menge LEERE kommen.

  1. echo $begrüßung;

    ich bin heute zufällig auf die Ctype Funktionen gestossen. Nicht schlecht dachte ich und wundernswert, warum bei den typischen Fragen zu Formularüberprüfungen selten, ich hatte es noch nie gesehen, empfohlen wurde.

    Es gibt noch einige weitere unbekannte Bestandteile PHPs, beispielsweise die Filter Functions.

    Nach ein wenig Nachforschung, fand ich den Hauptgrund darin, weil zb. Ctype Funktionen ctype_digit() nur mit Strings zurecht kommt:

    Das c steht ja auch für Character und Zahlen(typen) sind keine Zeichen(ketten).

    Na gut, dachte ich wär ja auch zu schön gewesen, was soll ich mich also damit rumärgern, bleibe ich doch gleich bei is_int oder is_numeric, auch wenn ich da einiges anpassen muss, den das problem ist ja:

    1. Kommt eine (scheinbare) Zahl an oder ist es doch ein String, der aussieht wie eine Zahl? Was ein Problem bei is_int sein könnte

    is_int() macht eine Typprüfung, keine Inhaltsauswertung. Kommt in einem String eine Ziffernfolge daher ist das kein Integer.

    1. 2.455 oder 2,44 sind auch Zahlen, ok kein integer aber somit geht is_numeric schon mal nicht, wenn ich nur Integer akzeptieren will.

    Das Komma ist kein Bestandteil einer von PHP akteptierten Zahl.

    Es dürfe Zahlen von 0-unendlich eingegeben werden.

    Zahlentypen haben einen definierten Wertebereich. "Unendlich" ist also schon mal nicht als Zahl möglich, nur als aus Ziffern bestehender String. Außerdem kommen Benutzereingaben immer als String daher (Ausnahmen sind für die typische PHP-Anwendung nicht relevant).

    Die Werte können intern erzeugt werden, aber auch von einem Formular kommen.

    Auch "intern erzeugte" Zahlen müssen sich an den Wertebereich des jeweiligen Typs halten.

    Welche Funktion(unter Berücksichtigung der notwendigen Anpasssung des Werte an die Funktion)sollte ich nun, und warum, dafür nutzen?

    Wenn du mit den Zahlen rechnen willst, musst du dich den Einschränkungen des jeweiligen Zahlentyps unterwerfen. Wenn du mit größeren Zahlen rechnen willst, nimm GMP oder BC Math aus den Mathematical Extensions. Dann musst du aber mit Strings (oder GMP-Ressourcen) hantieren. Ansonsten brauchst du sowieso Strings und kannst die String-Funktionen (ctype) verwenden. Und dann gibt es ja noch die oben erwähnten Filter.

    Oder doch besser $pattern = '/\d*/';?

    Dafür brauchst du Strings und ... na du weißt schon.

    ps. Kann mal Jemand sagen warum hier oft noch unzählige Zeilenumbrüche vorhanden sin,

    Drück nicht so oft Enter!

    echo "$verabschiedung $name";

  2. Guten Tag,

    Welche Funktion(unter Berücksichtigung der notwendigen Anpasssung des Werte
    an die Funktion)sollte ich nun, und warum, dafür nutzen?
    Oder doch besser $pattern = '/\d*/';?

    Ich habe folgendes Skript gerade mal durch einen Profiler (xdebug) geschoben:

    <?php  
      
    echo 'Saving to: ', xdebug_get_profiler_filename(), PHP_EOL;  
      
    define('LOOP', 1000000);  
    define('TEST', 234.456);  
      
    for($i = 0; $i < LOOP; $i++)  
    {  
        ctype_digit(strval(TEST));  
    }  
      
    for($i = 0; $i < LOOP; $i++)  
    {  
        preg_match('!^\d+$!', TEST);  
    }  
      
    for($i = 0; $i < LOOP; $i++)  
    {  
        filter_var(TEST, FILTER_VALIDATE_INT);  
    }  
    ?>  
    
    

    Das Ergebnis (Achtung, 4.5 MB) ist recht interessant: filter_var() und ctype_digit() sind nahezu gleich schnell. ctype_digit ist einen Tick schneller, allerdings verliert die Version ihren Geschwindigkeitsvorteil nur durch den Aufruf von strval() - ansonsten wäre ctype_digit() nahezu sieben mal so schnell wie filter_var().
    Wie erwartet verliert preg_match() deutlich, denn es benötigt nahezu die doppelte Zeit von filter_var().

    Man müsste mal schauen, ob es noch eine bessere Lösung für strval() gibt, dann würde die ctype_digit()-Version nämlich deutlich gewinnen.

    Gruß
    Christoph Jeschke

    --
    Zend Certified Engineer
    Certified Urchin Admin
    1. Hi Christoph,

      ansonsten wäre ctype_digit() nahezu sieben mal so schnell wie filter_var().

      nicht schlecht. Noch eine Frage, warum nutzt du strval(TEST), wäre $x=(string)$x nicht ausreichend bei der Verwendung von ctype_digit()?

      gruss
      Peter

      1. Guten Tag,

        nicht schlecht. Noch eine Frage, warum nutzt du strval(TEST), wäre
        $x=(string)$x nicht ausreichend bei der Verwendung von ctype_digit()?

        Hatte keinen besonderen Grund. Mir fiel strval() nur als erste Cast-Funktion ein.
        Es ist ziemlich sicher sogar performanter, den Aufruf nur ein mal zu machen.
        Daten, die per Formular übergeben werden sind übrigens immer Strings (oder Arrays aus Strings).

        Gruß
        Christoph Jeschke

        --
        Zend Certified Engineer
        Certified Urchin Admin
    2. echo $begrüßung;

      define('LOOP', 1000000);

      Wie immer bei solchen Labormessungen: Sie sind selten praxisrelevant. Der Unterschied wird erst bei einer sehr großen Anzahl an Wiederholungen spürbar. In der Praxis hat man nicht mehr als einige wenige. Die Einsparung fällt dann meist nur noch so gering aus, dass sie im Grundrauschen untergeht. Man steigert mit solchen Mikrooptimierungen seine Leistungsreserven nicht ausreichend, um einen nennenswerten Anstieg bei den verarbeitbaren Requests zu erreichen.

      echo "$verabschiedung $name";

      1. Guten Tag,

        Wie immer bei solchen Labormessungen: Sie sind selten praxisrelevant.

        Ack. Außerdem ist "premature optimization" eh übel.

        Gruß
        Christoph Jeschke

        --
        Zend Certified Engineer
        Certified Urchin Admin