Matthias Apsel: PHP - Zahlen mit Nullen auffüllen

Hallo alle,

ich habe ca. 500 maximal zweistellige Zahlen, die ich ggf. mit führender Null ausgeben möchte.

// Variante 1
$zahl = $ergebnis_einer_Rechnung;
if ( $zahl < 10 ) $zahl = "0" . $zahl;
// Variante 2
$zahl = str_pad ( $ergebnis_einer_Rechnung , 2 , "0" , STR_PAD_LEFT );
/* in der Hoffnung, das PHP das Ergebnis automatisch in einen String umwandelt */

Gibt es irgendetwas, was von vorherein gegen eine der beiden Möglichkeiten spricht?
Gibt es eine weitere, bessere Variante?

Der Schreibaufwand spricht für Variante 2. Das sollte aber nun wirklich das letzte Entscheidungskriterium sein, die Zeit habe ich noch nicht gemessen.

Bis demnächst
Matthias

--
Signaturen sind bloed (Steel) und Markdown ist mächtig.

akzeptierte Antworten

  1. Moin!

    Gibt es eine weitere, bessere Variante?

    • number_format() - für schöne Dezimalzahlen mit bestimmbarer Anzahl Nachkommstellen.
    • sprintf() - kann führende Nullen und auch sonst sehr viel (Tausendertrenner, Komma als Dezimaltrenner, Währungsymole, Affen, Birnen, Tortenstücke)
    • printf() - Variante von sprintf, die nicht zurück-gibt, sondern aus-gibt. Dürfte das sein, was Du gerade jetzt suchst.

    Für Dein Problem sieh Dir Beispiel #5 von sprintf() an.

    Das Manual nennt noch sscanf() - Überträgt einen String in ein angegebenes Format - das ist aber eher sowas wie der "Rückweg".

    Jörg Reinholz

    1. Hallo Jörg,

      • number_format() - für schöne Dezimalzahlen mit bestimmbarer Anzahl Nachkommstellen

      wie kann Matthias mit Hilfe von number_format eine führende 0 anzeigen lassen?

      Gruß Dennis

      1. Moin!

        • number_format() - für schöne Dezimalzahlen mit bestimmbarer Anzahl Nachkommstellen

        wie kann Matthias mit Hilfe von number_format eine führende 0 anzeigen lassen?

        Das war mehr dafür gedacht, denjenigen, die vielleicht mal via Suchmaschine "PHP Zahlen mit Nullen auffüllen" darauf stoßen, auch zu zeigen, wie das rechts des Kommas geht. (Der Titel ließ das offen...)

        Jörg Reinholz

    2. Hallo Jörg Reinholz,

      Gibt es eine weitere, bessere Variante?

      • sprintf() - kann führende Nullen und auch sonst sehr viel (Tausendertrenner, Komma als Dezimaltrenner, Währungsymole, Affen, Birnen, Tortenstücke)
      • printf() - Variante von sprintf, die nicht zurück-gibt, sondern aus-gibt. Dürfte das sein, was Du gerade jetzt suchst.

      Nein, ich bin noch in der Zusammenbauphase.

      Für Dein Problem sieh Dir Beispiel #5 von sprintf() an.

      Danke.
      Ja, dies leistet auch das Verlangte, gibt es eine optimale Variante?

      Bis demnächst
      Matthias

      --
      Signaturen sind bloed (Steel) und Markdown ist mächtig.
      1. Moin!

        Ja, dies leistet auch das Verlangte, gibt es eine optimale Variante?

        Da stellt sich die Frage nach der Definition von "optimal". Wie Denis schrieb ist str_pad aus seiner Sicht lesbarer... Das kann aber jeder in jeder Situation anders sehen.

        Jörg Reinholz

        1. Hallo,

          Da stellt sich die Frage nach der Definition von "optimal".

          genau, um etwas zu bewerten, muss man Kriterien definieren: Performance, Eleganz, Lesbarkeit, Skalierbarkeit, Wartbarkeit?

          Wie Denis schrieb ist str_pad aus seiner Sicht lesbarer... Das kann aber jeder in jeder Situation anders sehen.

          Ja, ich finde beispielsweise die sprintf-Lösung schöner, "lesbarer", weil sie das gewünschte Ergebnis explizit als Muster enthält und nicht als Algorithmus. Das Ausgabeformat ist außerdem viel leichter zu ändern als bei der str_pad-Variante, falls das mal gewünscht sein sollte.

          So long,
           Martin

          1. Hallo Martin,

            Ja, ich finde beispielsweise die sprintf-Lösung schöner, "lesbarer", weil sie das gewünschte Ergebnis explizit als Muster enthält und nicht als Algorithmus.

            dann müsste man sich tatsächlich mal überlegen, was "gute Lesbarkeit" bedeutet. Ich gehe dabei immer davon aus, wie viel jemand anderes im Zweifel nachschauen muss. Im Fall von str_pad muss man sich die Funktion ansehen, im Fall von sprintf muss man sich die Funktion plus das Muster ansehen, also mehr.

            Unabhängig davon kann ich aber sprintf intuitiver verwenden und persönlich auch besser lesen, einfach weil ich sie im Gegensatz zu str_pad schon zigmal verwendet habe und schon weiß, was das Muster bedeutet bzw. wie ich es lesen muss.

            Das Ausgabeformat ist außerdem viel leichter zu ändern als bei der str_pad-Variante, falls das mal gewünscht sein sollte.

            Das stimmt natürlich uneingeschränkt.

            Gruß Dennis

            1. Hi Dennis,

              Ja, ich finde beispielsweise die sprintf-Lösung schöner, "lesbarer", weil sie das gewünschte Ergebnis explizit als Muster enthält und nicht als Algorithmus.

              dann müsste man sich tatsächlich mal überlegen, was "gute Lesbarkeit" bedeutet.

              dass das ein sehr subjektives Kriterium ist, hat Jörg ja schon festgestellt.

              Ich gehe dabei immer davon aus, wie viel jemand anderes im Zweifel nachschauen muss. Im Fall von str_pad muss man sich die Funktion ansehen, im Fall von sprintf muss man sich die Funktion plus das Muster ansehen, also mehr.

              Ja, aber die printf-Funktionsfamilie kennt vermutlich ein Großteil der Softwareentwickler und Programmierer aus C. Ich gehe davon aus, dass die genannten Berufsgruppen (und viele verwandte) auch heute noch C als einen der Urahnen vieler Programmiersprachen lernen - ob sie es in ihrer eigenen täglichen Praxis dann anwenden, ist eine andere Frage. Ich betrachte C aber immer noch als das Programmierer-Äquivalent dessen, was "Grundlagen der Physik" für jeden Ingenieur ist: Basiswissen.

              Unabhängig davon kann ich aber sprintf intuitiver verwenden und persönlich auch besser lesen, einfach weil ich sie im Gegensatz zu str_pad schon zigmal verwendet habe und schon weiß, was das Muster bedeutet bzw. wie ich es lesen muss.

              Geht mir auch so.

              Ciao,
               Martin

            2. @@Der-Dennis

              dann müsste man sich tatsächlich mal überlegen, was "gute Lesbarkeit" bedeutet. Ich gehe dabei immer davon aus, wie viel jemand anderes im Zweifel nachschauen muss. Im Fall von str_pad muss man sich die Funktion ansehen, im Fall von sprintf muss man sich die Funktion plus das Muster ansehen, also mehr.

              Im Fall von str_pad muss ich mir die Funktion ansehen (wegen kenne ich nicht), im Fall von sprintf muss ich mir gar nichts ansehen, also weniger.

              Ein Hoch auf PHP, dass es für alles mindestens zwei Funktionen gibt und es dem Entwickler überlassen wird, sich im dem Wust zurechtzufinden.

              TL;DR: Ich denke, sprintf ist die bessere Wahl: einerseits weil konform zu anderen Programmiersprachen, andererseits flexibler:

              Das Ausgabeformat ist außerdem viel leichter zu ändern als bei der str_pad-Variante, falls das mal gewünscht sein sollte.

              LLAP 🖖

              --
              „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
          2. Hallo Der Martin,

            genau, um etwas zu bewerten, muss man Kriterien definieren: Performance, Eleganz, Lesbarkeit, Skalierbarkeit, Wartbarkeit?

            Performance, Lesbarkeit, aus letzterer imho unmittelbar folgend die Wartbarkeit. Eleganz und Lesbarkeit schließen sich beinahe aus. Wenn das mal nicht der Fall sein sollte, ist es wirklich die Lösung. Kann aber auch sein, dass ich Eleganz zu sehr mit Effizienz verbinde, wo wir schon wieder bei der Performance wären …

            Wie Denis schrieb ist str_pad aus seiner Sicht lesbarer... Das kann aber jeder in jeder Situation anders sehen.

            Ich habe mich jetzt für str_pad entschieden, aus Gründen der Lesbarkeit. Ich weiß, dass sich die Bedingungen nicht ändern werden, das heißt, die Zahlen bleiben maximal zweistellig und es wird immer links ein Zeichen aufzufüllen sein. Ich kann es schnell zu " " ändern, wenn ich es möchte. Die Performance wird bei geschätzen 500 Aufrufen pro Seite nicht so wirklich unterschiedlich sein, da sind höchstens meine Programmierschritte rundrum der Performancekiller. Die if-Variante finde ich auch sehr lesbar, vielleicht ist sie aber deutlich langsamer.

            Wie auch immer, ich werd jetzt mal an die frische Luft gehen und das deutlich weniger heiße und klebrige Wetter genießen. Wenn ich Lust und Zeit habe, kann ich ja mal die Zeit messen.

            Bis demnächst
            Matthias

            --
            Signaturen sind bloed (Steel) und Markdown ist mächtig.
            1. Hallo,

              genau, um etwas zu bewerten, muss man Kriterien definieren: Performance, Eleganz, Lesbarkeit, Skalierbarkeit, Wartbarkeit?

              Performance, Lesbarkeit, aus letzterer imho unmittelbar folgend die Wartbarkeit.

              soweit stimme ich zu.

              Eleganz und Lesbarkeit schließen sich beinahe aus.

              Im Gegenteil: Ich finde gerade effizient formulierte Lösungen (also ohne Schnörkel und Umwege) oft am besten lesbar und damit elegant, weil Effizienz (Performance) und Lesbarkeit miteinander einhergehen.

              Kann aber auch sein, dass ich Eleganz zu sehr mit Effizienz verbinde

              Das tu ich auch, und gerade darin liegt in meinen Augen auch die leichte Nachvollziehbarkeit.

              Wie auch immer, ich werd jetzt mal an die frische Luft gehen und das deutlich weniger heiße und klebrige Wetter genießen.

              Oha. Hier im Ländle sind immer noch schwüle 30°C, da habe ich noch keine große Lust zum Rausgehen. Wobei es hier drinnen mit 26..27°C auch nicht wirklich kühl ist, aber ein auf niedrigster Stufe laufender Ventilator und ein kühles Bierchen machen's erträglich. :-)

              Ciao,
               Martin

            2. @@Matthias Apsel

              Eleganz und Lesbarkeit schließen sich beinahe aus.

              Wirklich? Das hängt von der Definition von Eleganz ab, die im Auge des Betrachters liegt.

              “Any fool can write code that a computer can understand. Good programmers write code that humans can understand”
              —Martin Fowler

              Ich finde Code, den auch Menschen verstehen können, durchaus elegant.

              LLAP 🖖

              --
              „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
              1. Hallo Gunnar Bittersmann,

                Eleganz und Lesbarkeit schließen sich beinahe aus.

                Wirklich? Das hängt von der Definition von Eleganz ab, die im Auge des Betrachters liegt.

                “Any fool can write code that a computer can understand. Good programmers write code that humans can understand”
                —Martin Fowler

                Ich finde Code, den auch Menschen verstehen können, durchaus elegant.

                Genau. Deshalb hättest du noch den nächsten Satz mitzitieren sollen:

                Eleganz und Lesbarkeit schließen sich beinahe aus. Wenn das mal nicht der Fall sein sollte, ist es wirklich die Lösung.

                Bis demnächst
                Matthias

                --
                Signaturen sind bloed (Steel) und Markdown ist mächtig.
                1. @@Matthias Apsel

                  Genau. Deshalb hättest du noch den nächsten Satz mitzitieren sollen:

                  Eleganz und Lesbarkeit schließen sich beinahe aus. Wenn das mal nicht der Fall sein sollte, ist es wirklich die Lösung.

                  Der gegenseitige Ausschluss von Eleganz und Lesbarkeit klang bei dir wie der Normalfall; dem wollte ich widersprechen.

                  Wenn das ironisch gemeint war, ist mir dies entgangen.

                  LLAP 🖖

                  --
                  „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                  1. Hallo Gunnar Bittersmann,

                    Eleganz und Lesbarkeit schließen sich beinahe aus. Wenn das mal nicht der Fall sein sollte, ist es wirklich die Lösung.

                    Der gegenseitige Ausschluss von Eleganz und Lesbarkeit klang bei dir wie der Normalfall; dem wollte ich widersprechen.

                    Wenn das ironisch gemeint war, ist mir dies entgangen.

                    Nö, wars nicht. Ich halte elegante und lesbare Lösungen für das Optimum und bin tatsächlich der Meinung, dass sich Eleganz und Lesbarkeit beinahe ausschließen. Wobei Lesbarkeit natürlich auch noch vom Zielpublikum abhängt. Als unkonkrete Beispiele möchte ich eine Vielzahl deiner CSS-Ideen anführen. Je cleverer die Lösung ist, um so mehr Zeit muss man investieren um sie nachvollziehen zu können. Eine Lösung mit zusätzlichen Elementen etwa ist „lesbarer“ aber weniger elegant.

                    Aber ohne genaue Definitionen drehen wir uns im Kreis.

                    Bis demnächst
                    Matthias

                    --
                    Signaturen sind bloed (Steel) und Markdown ist mächtig.
                  2. Hallo Gunnar Bittersmann,

                    Eleganz und Lesbarkeit schließen sich beinahe aus. Wenn das mal nicht der Fall sein sollte, ist es wirklich die Lösung.

                    Mal noch ein Beispiel, wie es ja praktisch immer für die Weiterverarbeitung von DB-Abfragen genutzt wird.

                    while ($a = $b) :
                       // do something
                    endwhile;
                    

                    elegant?
                    lesbar?
                    für wen?
                    für wen nicht?

                    Bis demnächst
                    Matthias

                    --
                    Signaturen sind bloed (Steel) und Markdown ist mächtig.
                    1. Tach!

                      Mal noch ein Beispiel, wie es ja praktisch immer für die Weiterverarbeitung von DB-Abfragen genutzt wird.

                      while ($a = $b) :
                         // do something
                      endwhile;
                      

                      Besser ist, statt $b sowas wie fetch() zu notieren.

                      elegant?
                      lesbar?
                      für wen?
                      für wen nicht?

                      Für den, der das schon mal gemacht hat, ist das die einfachste Lösung unter den gegebenen Voraussetzungen, sprich: so wie die Fetch-Funktionen (in PHP) arbeiten. Sie geben nämlich zweierlei Werte zurück, einen Datensatz oder ein false. Das ist aber nicht sehr ausdrucksstark, weil man dieses Zwitterverhalten kennen muss, um diese Code-Schreibweise zu verstehen.

                      Zum Vergleich mal die C#/.NET-Vorgehensweise:

                      SqlDataReader reader = command.ExecuteReader();
                      
                      while (reader.Read()) 		{
                        Console.WriteLine("{0}\t{1}", reader.GetInt32(0), reader.GetString(1));
                      }
                      
                      reader.Close();
                      

                      Die Methode Read() gibt immer nur ein Boolean zurück. Sie holt den nächsten Datensatz in den Reader und gibt true, oder gibt false zurück, wenn nichts mehr zu lesen ist. Anders geht das bei stark typisierten Sprachen auch kaum. Damit wird nicht Status mit Nutzdaten vermischt. Die Nutzdaten fragt man dann später mit reader.GetIrgendwas() ab.

                      Besonders elegant ist das auch nicht, weil der Reader hier eine Nebenwirkung hat und die Get-Methoden je nach Datensatz unterschiedliche Ergebnisse liefern. Funktioenn, die Nebenwirkungen (englisch: side effects) haben, meidet man lieber. Und in der Tat nimmt man diese rudimentäre Art der Datenabfrage im Prinzip nicht für ernsthafte Dinge, sondern nimmt einen ORM oder ähnliches Framework, dass die Ergebnismenge als Enumerable liefert, man also mit foreach über sie laufen kann.

                      Kein Vorteil ohne Nachteil: die komfortablere Variante braucht mehr Code (für das Framework) und damit mehr Ausführungszeit. Sie ist meist deutlich langsamer als der hemdsärmliche Ansatz mit dem Reader. Aber solange die zusätzliche Zeit unspürbar ist, überwiegt der Komfortgewinn den Aufwand, den der Rechner treiben muss.

                      Elegant lesbar ist also die Komfortvariante, einen eleganten Ressourcenverbrauch hat die einfache.

                      dedlfix.

                      P.S. wieso kann der Kodehochleuchter kein C#?

                      1. Hallo,

                        so wie die Fetch-Funktionen (in PHP) arbeiten. Sie geben nämlich zweierlei Werte zurück, einen Datensatz oder ein false.

                        Es ist ja nicht nur so, dass die Funktion so arbeitet. Man muss auch wissen, dass die Zuweisung auch ein False zurück- bzw. weitergibt.

                        Gruß
                        Kalk

                      2. Tach,

                        P.S. wieso kann der Kodehochleuchter kein C#?

                        ist ein geplantes Feature für Version 1.2. Sieht allerdings nicht so aus, als würde das bald passieren.

                        mfg
                        Woodfighter

  2. Hallo Matthias,

    ich habe ca. 500 maximal zweistellige Zahlen, die ich ggf. mit führender Null ausgeben möchte.

    // Variante 1
    $zahl = $ergebnis_einer_Rechnung;
    if ( $zahl < 10 ) $zahl = "0" . $zahl;
    
    // Variante 2
    $zahl = str_pad ( $ergebnis_einer_Rechnung , 2 , "0" , STR_PAD_LEFT );
    /* in der Hoffnung, das PHP das Ergebnis automatisch in einen String umwandelt */
    

    Gibt es irgendetwas, was von vorherein gegen eine der beiden Möglichkeiten spricht?

    ich denke nicht. Ich würde aber str_pad nehmen, da es 1. besser lesbar ist und 2. einen Vorteil gegenüber der ersten Methode hat, wenn die Zahlen doch mal dreistellig oder so werden sollten, auch wenn das nicht Deine Anforderung ist.

    Gibt es eine weitere, bessere Variante?

    Eine weitere wäre sprintf, meiner Meinung nach aber schlechter (weil schlechter lesbar) als str_pad. Dafür ist sprintf aber insgesamt flexibler.

    Gruß Dennis

    1. Hallo Matthias,

      ich habe ca. 500 maximal zweistellige Zahlen, die ich ggf. mit führender Null ausgeben möchte.

      // Variante 1
      $zahl = $ergebnis_einer_Rechnung;
      if ( $zahl < 10 ) $zahl = "0" . $zahl;
      
      // Variante 2
      $zahl = str_pad ( $ergebnis_einer_Rechnung , 2 , "0" , STR_PAD_LEFT );
      /* in der Hoffnung, das PHP das Ergebnis automatisch in einen String umwandelt */
      

      Variante 3, für maximal 10 führende Nullen.:

          echo substr('0000000000' . $zahl, -10);
      

      solange es sich um Ziffern aus dem ersten Septett der Codetabelle handelt.

      scnr

      Grüße
      TS

  3. Gibt es eine weitere ... Variante?

    Du kannst es sogar mit regex machen. Ob es Sinn macht sei dahingestellt. Wenn $zahl ein string ist, wuerde ich string manipulation (str_pad, sprintf, ...) vorziehen.

    $zahl = preg_replace('/^\d$/', '0\0', $zahl);
    

    ^ Steht fuer den Anfang des Strings, \d fuer [0-9] und $ fuer das Ende des Strings. In der Ersetzung entspricht \0 dem, was auf das gesamte Suchmuster zutrifft, also der einziffrigen Zahl (regex101).

    Biba, Jonny 5

  4. Hallo Matthias,

    benutze einfach sprintf/printf - das kennt jeder und jeder weiss auf Anhieb, was dort gemacht wird, auch wenn er das spezielle Format erst nachlesen muss. Bei einer selbstgeschriebenen Lösung muss ich erst den Algorithmus verstehen um dann nachvollziehen zu können, was du dort tust. Best practices existieren aus exakt diesem Grund.

    LG,
    CK