Engineering Kiosk Episode #63 Spaß mit Zahlen: Under- und Overflows, Rückwärtslaufende Zeit, Negative Modulos und Währungsbeträge

#63 Spaß mit Zahlen: Under- und Overflows, Rückwärtslaufende Zeit, Negative Modulos und Währungsbeträge

Diese Episode in deiner Podcast-App hören...

Shownotes / Worum geht's?

Herausforderungen mit Zahlen in der Programmierung: Hidden bugs, Effekte auf die Realität und der richtige Umgang.

Der korrekte Umgang mit Zahlen in der Softwareentwicklung ist so wichtig wie die Reifen bei einem Auto, um es zu fahren.

Obwohl viele Entwickler sagen, Mathematik ist ein täglicher Bestandteil des Tages, so kommt man um die Verarbeitung von Zahlen nicht drum herum.

Doch wie schon früher in der Schule, kann der Umgang mit Zahlen sehr Herausfordernd sein. In dieser Episode sprechen wir über klassische Fehler, die beim Umgang mit Zahlen in Software gemacht werden, über skurriles Verhalten von Programmiersprachen aber auch über die Effekte dessen auf die reale Welt.

Es geht um Datentypen in Programmiersprachen und deren Wertebereiche, Probleme mit großen Zahlen und JSON, Währungsumrechnung und die korrekte Speicherung, Integer-Under- und Overflow, negative Modulo-Berechnungen, rückwärtslaufende Uhrzeiten und wie verschiedene Programmiersprachen sich bei der selben Berechnung anders verhalten.

Bonus: Ob Wolfgang Graf Zahl von der Sesamstraße kennt und warum JavaScript nicht gut in dieser Episode davonkommt.

Unsere aktuellen Werbepartner findest du auf https://engineeringkiosk.dev/partners

 

Das schnelle Feedback zur Episode:

👍 (top) 👎 (geht so)

Sprungmarken

(00:00:00) Intro

(00:01:03) Wie viel hat Informatik und Mathematik mit Softwareentwicklung zu tun und Bitoperationen

(00:06:24) Das heutige Thema: Probleme mit Zahlen (integer, float, double, decimals)

(00:08:09) Implizite Typ-Konvertierung bei Skriptsprachen und verschiedene Basen von Zahlen

(00:10:37) Division in MySQL mit Konvertierung nach JSON wird zum string

(00:12:39) Einstieg in Datentypen: int, int32, int64, signed, unsigned, Wertebereiche, Go und JavaScript

(00:20:58) Problem mit großen Zahlen: Twitter Tweet IDs, JavaScript BigInt und JSON

(00:26:51) Probleme mit Währungen: Rundungsfehler und die korrekte Speicherung

(00:35:31) Probleme mit Wertebereichen: Under- und Overflows, Signed und Unsigned Datentypen

(00:40:43) Under- und Overflow in der Realität: Das Jahr 2038 und 2036 Problem

(00:44:43) Probleme mit Zeit: Rückwärts Laufende Uhren, Leap-Seconds und Monotonic-Clock

(00:52:46) Probleme mit Modulo: Negative Zahlen führen zu verschiedenen Ergebnissen

(00:58:42) Weitere Probleme mit Zahlen: Portabilität, Zahlen-Basen, UUID und Bit-Operationen

Hosts

Feedback (gerne auch als Voice Message)

 

Transkript

Das Transkript wurde automatisiert per Speech-to-Text erstellt und kann daher Fehler enthalten.

Wolfi Gassler (00:00:01 - 00:00:05) Teilen

Gestatten, Graf Zahn. Und wissen Sie auch, warum ich so heiße?

Andy Grunwald (00:00:06 - 00:00:07) Teilen

Weil ich es liebe, zu zählen.

Wolfi Gassler (00:00:08 - 00:00:13) Teilen

Darum eins, zwei, drei, vier.

Andy Grunwald (00:00:18 - 00:01:14) Teilen

Das war Graf Zahl von der Sesamstraße beim Zählen. Dass jemand so viel Spaß mit Zahlen hat, hört man selten. Deswegen versuchen wir, das ganze Thema heute mal von einer anderen Seite aufzurollen. Wir sprechen über Herausforderungen mit Zahlen bei der Softwareentwicklung, aber eher aus der Sicht von skurrilem bzw. unerwartetem Verhalten. Es geht um Probleme mit großen Zahlen und JSON, Integer, Under- und Overflows sowie das Jahr 2038 und das Jahr 2036 Problem. Es geht um rückwärts laufende Uhrzeiten, negative Modulo-Berechnungen und wie verschiedene Programmiersprachen sich bei derselben Berechnung anders verhalten und vieles mehr. Wir hoffen, ihr habt genauso viel Spaß beim Zählen wie Graf Zahl. Und los geht's! Lieber Wolfgang, du hast ja einen Doktortitel und ich habe mich immer gefragt, wie viel Informatik mit Softwareentwicklung zu tun hat bzw. wie viel Softwareentwicklung steckt in Informatik, im Fachbereich Informatik.

Wolfi Gassler (00:01:15 - 00:01:18) Teilen

Was willst du da jetzt hören? Eine Prozentanzahl?

Andy Grunwald (00:01:18 - 00:01:26) Teilen

Nee, ob das einfach ein essenzieller Teil davon ist oder ob Informatik eigentlich gar nichts mit Softwareentwicklung zu tun hat oder oder oder.

Wolfi Gassler (00:01:26 - 00:01:47) Teilen

Ja, Softwareentwicklung ist ein Teil der Informatik, ist ja ganz klar. Es gibt ja irgendwie so einen Katalog von der ACM, glaube ich, von der American Computer Machinery, glaube ich, heißt die Abkürzung und die definiert da Computerbereiche, Informatikbereiche, Forschungsbereiche. Da ist Softwareentwicklung sicher einer davon, ja.

Andy Grunwald (00:01:47 - 00:02:00) Teilen

Zweite Frage. Wie viel hat Mathematik mit Softwareentwicklung zu tun? Wie viel Mathe muss man verstehen, um Software entwickeln zu können? Oder ist Mathematik ein essentieller und sehr wichtiger Bestandteil der Softwareentwicklung?

Wolfi Gassler (00:02:00 - 00:02:33) Teilen

Also einerseits gibt es immer extrem viele Studierende, die sich über die Mathe-Vorlesungen aufregen und vielleicht dann sogar raustroppen, weil das Informatikstudium so mathematisch ist. Auf der anderen Seite habe ich schon Programmiererinnen kennengelernt, die wenig Mathe-Ahnung hatten und vor allem, wenn es dann irgendwie tiefer nach unten geht und du keine Standard-if-Classes baust, die die Copilot machen kann, dann sieht man teilweise schon, dass Mathematik-Grundwissen oder tieferes Wissen schon ganz praktisch sein kann. Weil zum Beispiel, kennst du den Pipe Operator in der Programmiersprache?

Andy Grunwald (00:02:33 - 00:02:41) Teilen

Ich kenne den Spaceship Operator. Ich glaube, der wurde bei PHP und bei Ruby irgendwie eingeführt. Pipe Operator, ist das dasselbe wie auf der Bash-Kommandozeile, oder?

Wolfi Gassler (00:02:41 - 00:02:47) Teilen

Ja, ja, der ganz normale Pipe. Wenn du ein Oder machst, in deiner Go-Sprache, wie machst du denn da ein Oder? Mit zwei Strichen.

Andy Grunwald (00:02:47 - 00:02:50) Teilen

Ach so, du meinst... Ja, ja, ja, stimmt, ja.

Wolfi Gassler (00:02:50 - 00:02:52) Teilen

Was ist, wenn du nur einen Strich machst?

Andy Grunwald (00:02:52 - 00:02:53) Teilen

Das ist eine Bit-Operation, oder?

Wolfi Gassler (00:02:53 - 00:03:02) Teilen

Sehr gut, Herr Grunwald. Das wissen schon extrem viele Leute nicht mehr, was eine Bit-Operation ist. Oder weißt du, was eine Bit-Operation ist? Oder weißt du nur, dass es eine Bit-Operation ist?

Andy Grunwald (00:03:03 - 00:03:09) Teilen

Ich kriege das schon noch hin. Und ich glaube, das Gegenstück dazu ist natürlich auch das einfache Rund, also das einfache Kaufmannsrund. Ja, genau.

Wolfi Gassler (00:03:09 - 00:03:12) Teilen

Also was ist eine Bit-Operation?

Andy Grunwald (00:03:12 - 00:03:15) Teilen

Gegenfrage, was man eigentlich nicht tut. Wie sehr hasse ich Bit-Shifting?

Wolfi Gassler (00:03:16 - 00:03:18) Teilen

Moment, Bitshifting ist ein anderer Operator.

Andy Grunwald (00:03:18 - 00:03:37) Teilen

Das ist richtig. Selbes Feld. Ich hasse auch Bit-Operationen, ja? Weil mein Kopf da einfach zusammenfällt. Mein Kopf kann das einfach nicht... Ich versteh, was 0 und 1 sind, ja, und ich kann ne einfache Zahl so mit einem Bit und so, das krieg ich auch grad noch im Papier hin. Aber viel weiter darüber ist es echt... Also, mein Kopf kann das nicht verarbeiten. Ich weiß nicht, warum. Vielleicht bin ich auch einfach kein guter Softwareentwickler.

Wolfi Gassler (00:03:38 - 00:04:03) Teilen

Es ist ja eigentlich ganz einfach, weil wenn du die zwei Striche hast, ein logisches oder, das macht ja das gleiche wie das bitweise oder, nur das bitweise oder macht das pro Bit. Das heißt, das vergleicht halt dann die erste 1 oder die erste 1 oder die erste Stelle von der zweiten Zahl. Also das ist genau das gleiche. Das ist nur das eine auf Bitlevel und das andere auf logischer Ebene. Die Frage ist ja immer, muss man das Ganze wissen?

Andy Grunwald (00:04:03 - 00:04:13) Teilen

Ja, deswegen mache ich mal das mit einer dritten Frage ein bisschen einfacher. Wie viel hat Mathematik mit Zahlen zu tun? Also nicht mit Geldzahlen, sondern so mit Zahlen wie eins, zwei, drei und so.

Wolfi Gassler (00:04:13 - 00:04:20) Teilen

Ja, das ist so ähnlich, wie wenn du fragst, was hat Menschsein mit dir zu tun? Zahlen sind Teil der Mathematik.

Andy Grunwald (00:04:20 - 00:04:36) Teilen

Ja, doch, man sagt eigentlich schon, das ist die Zahl E, oder? Also ich meine, E ist ein Buchstabe in der Hinsicht. Die Zahl E drückt ja dann Wert aus oder die Zahl Pi. Pi ist ja keine Zahl, obwohl es 3,14 und so weiter ist, aber das Zeichen Pi ist ja keine Zahl und das Zeichen E ist ja auch keine Zahl.

Wolfi Gassler (00:04:36 - 00:04:39) Teilen

Doch, ist schon eine Zahl, ist nur eine sehr lange Zahl.

Andy Grunwald (00:04:39 - 00:04:41) Teilen

Nee, aber ich meine, die wird ja durch den Buchstaben repräsentiert.

Wolfi Gassler (00:04:41 - 00:04:43) Teilen

Ja, es gibt auch Buchstaben in der Mathematik.

Andy Grunwald (00:04:44 - 00:04:44) Teilen

Okay.

Wolfi Gassler (00:04:44 - 00:04:49) Teilen

Wir sagen übrigens Mathematik, nicht Mathe, Mathematik. Ganz wichtig, die österreichische Betonung.

Andy Grunwald (00:04:49 - 00:04:55) Teilen

Und bevor wir ins eigentliche, wirkliche Thema einsteigen, die viel wichtige Frage, Im Moment.

Wolfi Gassler (00:04:55 - 00:05:01) Teilen

Sind wir nicht so lange im Thema drin. Jetzt wird es spannend, was wir für ein Thema haben. Okay, unser Einsprecher hat das ja schon verraten.

Andy Grunwald (00:05:01 - 00:05:03) Teilen

In welchem Jahr wurdest du geboren, Wolfgang?

Wolfi Gassler (00:05:03 - 00:05:07) Teilen

Hallo, Datenschutz? Ich kann das ja nicht so in die Welt rausbussernen.

Andy Grunwald (00:05:07 - 00:05:09) Teilen

Aber Graf Zahl sagt dir noch was, oder?

Wolfi Gassler (00:05:09 - 00:05:10) Teilen

Graf was?

Andy Grunwald (00:05:10 - 00:05:11) Teilen

Die Sesamstraße.

Wolfi Gassler (00:05:11 - 00:05:13) Teilen

Kann ich nur von Hören sagen.

Andy Grunwald (00:05:13 - 00:05:18) Teilen

In der Sesamstraße gibt es Graf Zahl. Und Graf Zahl bringt den Kindern im Vorschulalter.

Wolfi Gassler (00:05:18 - 00:05:21) Teilen

Das ist eine Person, so wie dieses Brot da, oder?

Andy Grunwald (00:05:21 - 00:05:25) Teilen

Ich glaube, was du meinst, ist Bernd das Brot? Das ist eine andere Generation.

Wolfi Gassler (00:05:25 - 00:05:28) Teilen

Also das ist gar nicht Sesamstraße, okay.

Andy Grunwald (00:05:28 - 00:05:37) Teilen

Und ich weiß gar nicht, ob die Elemente, diese Dinger, die reden können, bei der Sesamstraße Menschen sind. Das ist eine andere Frage. Aber du kennst anscheinend nicht Graf Zahl.

Wolfi Gassler (00:05:38 - 00:05:39) Teilen

Ich kenne Graf Dracula.

Andy Grunwald (00:05:39 - 00:05:49) Teilen

Okay, Graf Zahl bringt den Kindern im Vorschulalter das Zählen von Dingen bei. Und vielleicht war das der Knackpunkt, warum du in der Programmierung immer in Probleme mit Zahlen rennst.

Wolfi Gassler (00:05:49 - 00:05:52) Teilen

Weil ich die Sesamstraße nicht gesehen habe damals.

Andy Grunwald (00:05:52 - 00:05:54) Teilen

Ja, weil du anscheinend Graf Zahlen nicht kennengelernt hast.

Wolfi Gassler (00:05:54 - 00:06:06) Teilen

Ich bin mir nicht sicher, ob es die Sesamstraße so in Österreich gegeben hat, vor dem ganzen Zeitalter des Kabelfernsehens. Ich kann mich zumindest nicht erinnern, dass ich die jemals gesehen habe als Kind oder so. Hat es die überhaupt schon gegeben, wie jung war?

Andy Grunwald (00:06:06 - 00:06:17) Teilen

Also sie läuft seit 1969. Ja, das geht sich knapp aus. Die erste deutschsprachige Ausstrahlung war im Januar 1973.

Wolfi Gassler (00:06:17 - 00:06:24) Teilen

Das geht sich leider immer noch aus. Aber irgendwie im österreichischen Fernsehen war die meines Wissens nicht vertreten. Wäre interessant.

Andy Grunwald (00:06:24 - 00:07:21) Teilen

Okay, für alle Leute, die Grafzahl nicht kennengelernt haben und somit bei Grafzahl nicht das Zählen von Dingen gelernt haben, für die Leute haben wir heute eine besondere Ebene. Und zwar sprechen wir wieder über ein Thema in der Softwareprogrammierung, wo irgendwie wir jeden Tag mit zu tun haben, aber wo ich öfters den Anstand habe, dass wir diesem ganzen Bereich sehr, sehr wenig Aufmerksamkeit schenken. Und zwar ist das einfach das Thema Herausforderungen oder vielleicht kann man auch schon Probleme mit Zahlen sagen, mit Integer, mit Floats, mit Doubles, mit Dezimals und so weiter und so fort. Also Vielleicht auch über diese Art von Problemen, da wo ihr sagt, geil, endlich mal bugfreie Software geschrieben und dann deployed ihr das und nach vier Monaten habt ihr falsche Werte in der Datenbank und ihr versteht, die fehlt nicht mehr. Wir haben heute einfach mal ein paar klassische Real-World-Probleme rausgesucht, wo man ab und zu darüber schmunzeln kann und ab und zu sagt, what the fuck ist, was geht denn hier ab.

Wolfi Gassler (00:07:21 - 00:07:30) Teilen

Also was wir eigentlich machen ist, dass der Andi heute diesen Graph Zahl spielt für die Informatik. Sehe ich das richtig, Andi? Du erklärst uns jetzt die mathematische Welt.

Andy Grunwald (00:07:30 - 00:07:48) Teilen

Die erste Note in meiner Statistik 1 Klausur war, glaube ich, eine 3,7. Ich habe mich sehr gut vorbereitet gefühlt, bin da reingegangen, bin rausgegangen, war eine mega Leistung und bin gerade mit Statistik 1 mit so einer 3,7 da dabei geschlittert. Für Leute, die es nicht wissen, 4,0 ist auch noch bestanden und alles drüber ist halt, bitte wiederholen Sie die Klausur.

Wolfi Gassler (00:07:48 - 00:07:55) Teilen

Ja, aber Statistik hat ja wenig mit Zahlen zu tun. Zumindest mit dem Programmieranteil der Zahlen, würde ich mal sagen.

Andy Grunwald (00:07:55 - 00:08:08) Teilen

Und genau deswegen habe ich ja gefragt, was hat Softwareentwicklung mit der realen Informatik zu tun? Ich habe mir nämlich irgendwo gehört, nicht ganz so viel, aber ich versuche es so ein bisschen. Und als kleine Vorwarnung, irgendwie habe ich das Gefühl, bei der heutigen Folge wird JavaScript nicht so gut davon kommen.

Wolfi Gassler (00:08:09 - 00:08:18) Teilen

Was war denn dein letzter Fuckup, den du so erlebt hast mit Zahlen, wenn du irgendwie mit Zahlen hantiert hast, jetzt beim Programmieren oder sonst irgendwo in letzter Zeit?

Andy Grunwald (00:08:18 - 00:08:27) Teilen

Wo ich sehr oft reinrenne, ist bei Skriptsprachen die Typkonvertierung von String nach Int oder ähnliches, besonders wenn das mit einem Null-Präfix ist.

Wolfi Gassler (00:08:27 - 00:08:31) Teilen

Was meinst du mit einem Nullpräfix? Was passiert da genau? Kannst du das kurz erklären?

Andy Grunwald (00:08:31 - 00:08:38) Teilen

Naja, je nachdem welche Sprache du hast, kann diese Zahl unter anderem auch als Oktalzahl oder ähnliches...

Wolfi Gassler (00:08:38 - 00:08:40) Teilen

Was ist denn eine Oktalzahl?

Andy Grunwald (00:08:40 - 00:09:00) Teilen

Eine Oktalzahl ist eine Zahl mit der Basis 8, eine Dezimalzahl ist eine Basis 10, eine Binärzahl ist eine Basis 2 und eine Hexadezimalzahl ist die Basis 16, Wolfgang. Das bedeutet, du hast natürlich auch verschiedene Arten von Zahlen in der Programmierung, die natürlich dann auch anders repräsentiert werden. Zum Beispiel kannst du sagen, okay.

Wolfi Gassler (00:09:00 - 00:09:07) Teilen

Und wie repräsentiert man eine Oktalzahl? Ich kenne ja Hexadezimal mit 0x, aber was ist denn dann ein Oktal?

Andy Grunwald (00:09:07 - 00:09:18) Teilen

Soviel ich weiß, in vielen Programmiersprachen repräsentiert man eine Zahl mit Oktal, wenn die unter anderem mit einer 0 beginnen kann, aber dann nur die Zahlen 0 bis 7 auch drin hat. Je nach Programmiersprache ist es, glaube ich, ein bisschen anders.

Wolfi Gassler (00:09:18 - 00:09:51) Teilen

Das ist ja schon so ein großes Problem, dass man eigentlich ja wenig Ahnung hat, wie die Programmiersprache immer Sachen interpretiert. Und sogar wenn man mit Programmiersprachen lange arbeitet, dann sind ja so klassische Zahlenprobleme die, die man selten antrifft, aber die dann, wenn sie mal auftreten, wirklich ein großes Problem. produzieren, weil man eben keine Ahnung hat, dass da irgendwo was im Hintergrund umkonvertiert wird automatisch oder oktal interpretiert wird. Das heißt, wenn ich dann 0 7 zum Beispiel schreibe oder 0 7 6, dann könnte das oktal interpretiert werden.

Andy Grunwald (00:09:51 - 00:10:36) Teilen

Also, wenn man zum Beispiel JavaScript im Strict-Mode laufen lässt, dann kriegt man sogar einen Syntax-Error, weil die sagen, null-prefixed-octal-literals sind deprecated. Also, es geht halt schon in die Richtung, je nachdem, welche Programmiersprache man wählt. Aber das ist so der Klassiker, wenn ich sage, implizite Typkonvertierung, nicht explizite, implizite, das bedeutet, wo die Runtime-Engine, wo der Compiler oder der Interpreter Typen für mich konvertiert, oder wo ich gegebenenfalls Typen nicht ganz unter Kontrolle habe, kann natürlich auch sein. Und dann gegebenenfalls noch eine unglückliche Zahl habe, weil du hast ja keine Oktalzahl, wenn du in der Zahl einen 9 hast, dann ist es ja keine Oktalzahl mehr und somit kann es dann nicht mehr als Oktalzahl interpretiert werden. Also du merkst schon, da müssen dann so ein paar Sachen halt schon zusammenkommen, aber das ist so, wo ich öfter mal reinrenne.

Wolfi Gassler (00:10:36 - 00:10:47) Teilen

Ich habe gerade ganz kürzlich in der MySQL-Datenbank eine Division durchgeführt, also in einem SQL-Statement. Was kommt da als Typ raus, Andi? Was glaubst du?

Andy Grunwald (00:10:47 - 00:10:47) Teilen

Keine Ahnung.

Wolfi Gassler (00:10:48 - 00:10:56) Teilen

Ja, es ist gar nicht so leicht zu sagen. Meine Annahme war, es ist float oder so. Habt ihr das Ding in JavaScript einfach nach JSON konvertiert? Was kommt raus?

Andy Grunwald (00:10:57 - 00:10:59) Teilen

Ich springe von einem Raten ins andere.

Wolfi Gassler (00:10:59 - 00:12:17) Teilen

Also bei JavaScript und JSON kann man immer, wenn man keine Ahnung hat, am besten String sagen. Das stimmt immer. Auf jeden Fall ist am Ende ein String rausgekommen mit dem Ergebnis und es war wirklich schwierig für mich zu verstehen, warum das passiert, weil es ja eine Division ist, da ist irgendwie ein Float, Double, was auch immer, da sollte sauber konvertiert werden. Javascript habe ich auch die Zahl explodiert, ist dann ein String und die Frage war für mich ja auch, Wo liegt das Problem? Liegt es an der Datenbank? Liegt es in JavaScript? Liegt es an der JSON-Library? Also du hast ganz viele Punkte, wo dieses Problem auftreten kann. Und das Debugging ist dann auch nicht so leicht, weil du musst herausfinden, okay, wo werden da was für Datentypen verwendet? Und am Ende ist es einfach so, dass das Ganze ein sogenannter New Decimal Wert ist. der ganz speziell definiert ist und Javascript kann natürlich mit sowas nicht umgehen und wandelt das dann einfach in String um, damit man auf der sicheren Seite ist und keine Präzisionsfehler oder ähnliche Dinge hat. Also bei diesem einfachen Fall nur Datenbank zu chasen hast du schon drei verschiedene Punkte, wo was schief gehen kann. wo du keine Ahnung hast, was die jeweiligen Libraries machen und die Datenbank, wie der Datenbanktreiber funktioniert. Und es hat mir durchaus einige Zeit gekostet, bis ich da wirklich dahinter gestiegen bin, wo da welcher Datentyp wie verwendet wird und warum.

Andy Grunwald (00:12:17 - 00:12:45) Teilen

Also, liebe Hörerinnen und Hörer, ihr merkt schon, das Arbeiten mit Zahlen ist nicht ganz einfach, wenn ein Mensch mit einem Doktortitel in Datenbanken und Wissenssysteme und so weiter und schon in solchen einfachen Fällen von einer Programmiersprache mit JSON-Konvertierung und der Speicherung in einer Datenbank gegen irgendwelche Wände rennt. Genau deswegen sprechen wir mal über ein paar Herausforderungen mit dem Arbeiten von Zahlen heute. Bevor wir aber in die Probleme einsteigen, machen wir mal einen ganz kurzen Einstieg in Datentypen, damit wir mal jeden abholen.

Wolfi Gassler (00:12:45 - 00:12:46) Teilen

Also Kraftzahl, leg los.

Andy Grunwald (00:12:47 - 00:12:53) Teilen

Grafzahl, wenn Grafzahl das folgende in der Sesamstraße als Wissen vermittelt, dann fände ich das schon ziemlich cool, muss ich zugeben.

Wolfi Gassler (00:12:54 - 00:12:56) Teilen

Also an die Zahl, an die Zahl.

Andy Grunwald (00:12:56 - 00:13:07) Teilen

Also generell kann man erst mal sagen, welche Datentypen es gibt, unterscheidet sich von der Programmiersprache und nicht alle Datentypen werden von allen Programmiersprachen unterstützt.

Wolfi Gassler (00:13:07 - 00:13:15) Teilen

Was sind denn Datentypen von Zahlen überhaupt? In JavaScript kann ich da meine Zahl hinschreiben, das funktioniert. Da hat überhaupt nichts mit Datentypen zu tun.

Andy Grunwald (00:13:15 - 00:14:21) Teilen

Genau, man hat natürlich verschiedene Arten von Programmiersprachen. Besonders die Scriptsprachen oder auch moderne, kompilierte Programmiersprachen versuchen den Typ zu erraten. Da muss man ihn gar nicht wirklich definieren. Zum Beispiel in Go Variable Doppelpunkt gleich 5 initiiert automatisch einen Integer. Und bei PHP kannst du auch irgendwas definieren und bei JavaScript auch. Du kannst aber auch in diesen Sprachen explizit sagen, okay, das ist ein Integer oder das ist ein 64-Bit-Integer. Das bedeutet, Implizite Typangabe, explizite Typangabe ist schon mal ein Bereich. Welche Datentypen es gibt, wie gesagt, unterscheidet sich pro Programmiersprache. Zum Beispiel in der Sprache Go von Google gibt es mindestens acht Datentypen für einen Integer. Und zwar unterscheiden die sich in der A, in der Bitgröße. Also es gibt einen 8-Bit-Integer, 16, 32, 64. Dann gibt es alle Varianten davon nochmal unsigned und signed. Das bedeutet, kann man da ein Vorzeichen mitspeichern, ja oder nein. Das hat natürlich auch Einfluss auf den Wertebereich und der Wertebereich ist einfach, wie viele Zahlen kann man nämlich in diesem Integer-Datentyp speichern.

Wolfi Gassler (00:14:21 - 00:14:31) Teilen

Warum mache ich denn jetzt überhaupt so ein Int8 oder so, wo ich nur ganz wenig Platz habe, jetzt von minus 128 bis 127, minus 1 ist es immer?

Andy Grunwald (00:14:31 - 00:14:58) Teilen

Naja, das tolle ist, wenn du jetzt sagst, okay, man nimmt ein Int8, dann hast du automatisch den Wertebereich begrenzt, weil man kann halt nur minus 128 bis 127 speichern, das ist die eine Baustelle. Und ich glaube auch, dass du damit der Hardware bzw. dem Computer die Möglichkeit gibst, den Speicherbereich auch noch weiter zu optimieren, weil du müsstest dann nicht immer einen 64-Bit-Integer speichern, weil du brauchst halt den ganzen Platz nicht. Ob das jetzt wirklich möglich ist, weiß ich jetzt nicht.

Wolfi Gassler (00:14:59 - 00:15:34) Teilen

Ich glaube, die meisten Programmiersprachen allokieren wirklich 64-Bit. Vielleicht ist das sogar hardwarebedingt gar nicht anders möglich. Ich glaube, in Java ist es meines Wissens immer so, das war früher schon so, auf 64-Bit-Systemen wurden auch immer 64-Bit allokiert. Aber ob es da mittlerweile schon Optimierungen gibt, da bin ich auch zu wenig in der Softwareentwicklung drin, muss ich zugeben. Aber man könnte es zumindest optimieren und Datenbanken, da spielt es natürlich eine große Rolle, wenn du das dann wirklich irgendwo ablegst. Die Datenbanken optimieren dir das natürlich auf jeden Fall, den Speicherbereich.

Andy Grunwald (00:15:34 - 00:16:06) Teilen

Auf jeden Fall gibt es Programmiersprachen wie zum Beispiel Go, da kannst du sagen, okay, ich möchte sogar ein unsigned Integer mit 64 Bit haben. Das bedeutet eine Ganzzahl, die einen Wertebereich hat von 0 bis, und jetzt kommt eine ganz lange Zahl mit 20 Stellen. Das bedeutet, da kann man nicht die Zahl minus 1 drin speichern, weil sie einfach das Vorzeichen nicht mitspeichert, weil sie nicht vorzeichenbehaftet ist. Auf der anderen Seite kann man natürlich auch ein int 64 deklarieren. Da hat man einen Wertebereich von minus eine 19-stellige Zahl bis plus eine 19-stellige Zahl.

Wolfi Gassler (00:16:06 - 00:16:08) Teilen

Also groß.

Andy Grunwald (00:16:08 - 00:16:14) Teilen

Groß. Dann gibt es natürlich die ganze Sache auch noch mit Fließkomma-Zahlen. Float oder Double heißt das in vielen Programmiersprachen.

Wolfi Gassler (00:16:14 - 00:16:17) Teilen

Moment, was ist der Unterschied zwischen Float und Double?

Andy Grunwald (00:16:17 - 00:16:25) Teilen

Das ist glaube ich wirklich der zu speichernde Wertebereich und die Präzision im Fließkomma Bereich, wenn mich das jetzt gerade nicht trickt.

Wolfi Gassler (00:16:26 - 00:17:05) Teilen

Also es ist eigentlich ganz einfach zu merken, Double heißt Double, weil einfach doppelt so viele Byte verwendet werden. Das heißt, im klassischen Verständnis sind es einfach 8 statt 4 Byte. Das heißt, du hast eine höhere Präzision und darum heißt das Ding Double. Dass das mittlerweile nicht mehr so ganz hundertprozentig genau definiert ist. MySQL hat ja teilweise auch andere Definitionen. Du hast gerade richtig gesagt, es gibt float 32, float 64. Also das ist ja eigentlich schon wieder das Gleiche. Also es ist nicht mehr so klar definiert, aber das Ursprüngliche, also die klassische C-Definition war einfach Double, 8-byte, float 4-byte. Einfach mehr Genauigkeit.

Andy Grunwald (00:17:05 - 00:18:12) Teilen

Und ich hatte gerade gesagt, es unterscheidet sich pro verwendeter Sprache. In JavaScript sieht die ganze Sache anders aus. In JavaScript hat man gar keinen Datentyp Integer, sondern hat man nur den Typ Number. Und Number ist eine Double-Precision-64-Bit-Zahl im Binary-Format. Passwort-Bingo. Also da hat man automatisch eine Fließkomma-Zahl. Also jede Zahl in JavaScript ist eine Fließkomma-Zahl. Und die Eigenheit an JavaScript ist jetzt folgende. Die Größe und Genauigkeit der gespeicherten Zahl ist begrenzt. Das bedeutet, in JavaScript können Ganzzahlen nur im Bereich 2 hoch 53, im negativen und positiven Bereich, ohne Genauigkeitsverlust dargestellt werden. Es gibt eine Konstante, die nennt sich number.maxSafeInteger, da kommt eine Zahl raus, die ist 16 Stellen groß. Wenn ihr euch in diesem Wertebereich bewegt, was ich würde mal fast sagen sehr viele Applikationen tun, dann kann die Zahl von JavaScript mit dem Datentyp Number ohne Genauigkeitsverlust dargestellt werden. Die Zahl Number selbst kann aber eine viel größere Zahl speichern, und zwar eine Zahl bis zum maximalen Value 2 hoch 1024. Wie viele Stellen sind das, Wolfgang?

Wolfi Gassler (00:18:12 - 00:18:13) Teilen

Viele.

Andy Grunwald (00:18:13 - 00:18:18) Teilen

Aber da ist man dann in einem Bereich, wo es Genauigkeitsverluste geben kann.

Wolfi Gassler (00:18:18 - 00:18:20) Teilen

Wodurch entstehen diese Genauigkeitsverluste?

Andy Grunwald (00:18:20 - 00:18:34) Teilen

Meines Wissens nach durch Rundungsfehler und wie sehr man die Precision nach dem Komma speichern kann. Da sollte man jetzt den Menschen mit dem Doktortitel fragen. Ich habe ja nur Bachelor und auch nur in Wirtschaftsinformatik. Ich bin ja sozusagen dumm.

Wolfi Gassler (00:18:34 - 00:19:31) Teilen

Ja, da müsste man natürlich jetzt sehr tief in das Rapid Hole runtergehen. Das ist immer die beste Ausrede, wenn man keine Ahnung hat. Aber grundsätzlich hängt es natürlich zusammen mit der Darstellung bzw. mit dem Speicherformat von Fließkomma-Zahlen, weil es ist ja nicht so, dass die Zahlen genauso gespeichert werden, wie du sie eingibst. Also du sagst, okay, du hast jetzt, wenn du 15,3 hast oder so, dann wird da 15 gespeichert und der 3 am Ende als eigene Zahl, sondern es wird ja umgewandelt in eine interne Repräsentation, die die CPU auch versteht. Und durch diese Umwandlung In so eine Gleitkomma-Repräsentation können die Details am Ende verloren gehen und dadurch kannst du einen Rundungsfehler geben, weil du eben Informationen von dieser Zahl verlierst. Und damit hast du eigentlich immer zu kämpfen, egal ob du Float, Double, was auch immer du verwendest, weil es kann immer diese Edge Cases geben. Was heißt Edge Cases eigentlich auf Deutsch? Corner Cases? Ausnahmefälle? Andy, wie heißt sowas?

Andy Grunwald (00:19:32 - 00:19:35) Teilen

Ausnahmefall beziehungsweise Fall, der selten auftritt, würde ich sagen, ja.

Wolfi Gassler (00:19:35 - 00:19:46) Teilen

Also der seltene Auftretungsfall ist dann, dass man da Information verliert und dann plötzlich eine andere Zahl rausbekommt. Und das ist ja eigentlich das Gefährliche an diesem ganzen Float-Double-Wert.

Andy Grunwald (00:19:46 - 00:19:49) Teilen

Und wie löse ich das Problem jetzt? Wie kriege ich das hin, dass ich damit sicher umgehe mit Leitkommazahlen?

Wolfi Gassler (00:19:49 - 00:20:14) Teilen

Ja, es kommt darauf an, was du machen willst. Da kommen wir eh später noch drauf. Aber wenn du Float und Double verwendest, hast du einfach Ungenauigkeiten. Damit musst du einfach leben. Das ist so. Du kannst mehr Genauigkeit draufschieben, indem du mehr Bytes dazuhängst, aber die Ungenauigkeit an sich, die bleibt. Die kannst du nicht verhindern mit diesen Datentypen. Da brauchst du andere Konstrukte dafür. Aber bleiben wir mal bei JavaScript, weil da gibt es sowieso nur den Number-Typ.

Andy Grunwald (00:20:14 - 00:20:58) Teilen

Ja, das ist nicht ganz richtig. Bei JavaScript gibt es nämlich auch noch einen anderen Datentyp, der nennt sich BigInt. Und der BigInt-Datentyp ist BigInt, eine große Ganzzahl. Mit dem BigInt kannst du auch in einem Wertebereich über MaxSafeInteger sicher agieren. Diese Zahlen haben in der Regel ein N als Suffix, also hinten dran steht einfach ein N. Und das tolle ist, sie können sogar mit einer normalen Zahl verglichen werden. Zwar nicht strikt, also eine Number ist nicht ein BigInt, wenn man sie strikt vergleicht mit drei gleicher Zeichen, aber wenn man sie loosely miteinander vergleicht, sondern mit zwei, dann klappt das sogar. Also in der Hinsicht ist JavaScript dann schon so ein bisschen einfacher gehalten als zum Beispiel Go, wo Go etliche Datentypen hat, hat JavaScript genau zwei.

Wolfi Gassler (00:20:58 - 00:21:02) Teilen

Und kann ich dann mit diesem BigInt endlich meine Twitter-IDs abspeichern?

Andy Grunwald (00:21:02 - 00:21:07) Teilen

Ja, könntest du, doch da gibt es so ein anderes Problem und zwar nennt sich das JSON.

Wolfi Gassler (00:21:07 - 00:21:11) Teilen

Okay, aber du kennst scheinbar auch dieses Twitter-ID-Problem.

Andy Grunwald (00:21:11 - 00:22:21) Teilen

Ja, das folgendermaßen. Twitter ist ja eine Plattform, die wird ja sehr viel genutzt. Und zwar hat jeder Tweet eine ID inzwischen. Und ich weiß gerade nicht, wie viele Stellen die Twitter-ID hat. Auf jeden Fall mehr als 16 Stellen. Und jetzt ist es in JavaScript so, hatten wir gerade gesagt, dass der Number-Datentyp einen MaxSafeInteger-Wertebereich hat von 16 Stellen. Alles drüber ist so ein bisschen ungenau und das Problem ist, wenn du dann mit der ID rechnest, dann kriegst du ein anderes Resultat raus, was dann auf eine andere Twitter-ID lenkt, was dann einfach ein anderer Tweet ist. Relativ doof. Das hat die Twitter-API dazu bewegt, ihre Tweet-IDs einmal als Integer rauszugeben, aber auch als String-Datentyp. Das bedeutet, quatschst du mit der Twitter-API, kriegst du die Tweet-ID zweimal in zwei verschiedenen Formaten. Und das haben sie nur gemacht, damit JavaScript die Tweet-IDs lesen kann. Also wenn du mit JavaScript und der Twitter-API arbeiten musst, dann nutze bitte die String-Repräsentation der Tweet-ID. Jetzt könnte man fragen, Moment mal, du hast ja gerade von dem Java-Skript-Datentyp BigInt gesprochen. Warum nutzt denn Twitter nicht BigInt? Ja, sagen wir, es ist kompliziert.

Wolfi Gassler (00:22:21 - 00:22:25) Teilen

Funktioniert der überhaupt überall mittlerweile? Kann ich den in jedem Browser verwenden?

Andy Grunwald (00:22:26 - 00:22:31) Teilen

Wenn du mit dem Internet Explorer 6 unterwegs bist, glaube ich nicht, aber ich weiß es nicht. Sollen wir mal Can I Use checken?

Wolfi Gassler (00:22:31 - 00:22:33) Teilen

Check mal. Andi checkt jetzt live.

Andy Grunwald (00:22:33 - 00:22:51) Teilen

Sieht auf jeden Fall sehr grün aus, würde ich schon sagen. BigInt kann man relativ gut überall nutzen, in jedem Browser. Aber nur weil wir JavaScript verwenden, heißt das nicht, dass wir im Browser sind, Wolfgang. Denn auch serverseitig gibt es da ein Problem, weil da gibt es dieses tolle Format, das nennt sich JSON, JavaScript Object Notation.

Wolfi Gassler (00:22:51 - 00:22:56) Teilen

Was hat denn jetzt JSON mit Server zu tun? Du kannst JSON auch im Client verwenden, lieber Backend-Developer.

Andy Grunwald (00:22:56 - 00:23:38) Teilen

Das ist richtig, das ist richtig. Es ist nun mal so, dass die Twitter-API als Response JSON gibt. Und die JSON.Parse-Funktion kann kein BigInt. Zumindest nicht im JavaScript. Das bedeutet, auch wenn du die Integer-Repräsentation der Tweet-ID verarbeiten möchtest, kriegst du es im JavaScript aktuell nicht hin. Das TC39-Komitee, das ist das Komitee, was sich halt um die Sprache, ECMAScript, JavaScript und so weiter kümmert, die arbeiten gerade dran, dass der JSON-Parsing-Standard auch Support für BigInt bekommt. Und das hoffentlich führt dazu, dass wir endlich große Zahlen in API-Responses dann auch als große Zahlen verarbeiten können und nicht als Strings.

Wolfi Gassler (00:23:39 - 00:24:51) Teilen

Und da ist ja schon wieder das Problem, wenn du sagst, diese JSON-Parse-Funktion kann das nicht. Das ist ja bei JavaScript auch das Problem, dass man das gar nicht sagen kann, weil es kommt ja darauf an, was für eine JavaScript-Implementierung das ist, was für Engine das Ganze ist, weil es kann ja wieder jede Engine selbst definieren oder programmieren, sollte sie natürlich nicht und die halten sich natürlich schon an die Standards. Aber theoretisch, dadurch du nicht den einen Compiler hast wie bei Go, Wobei bei Go gibt es vielleicht auch mittlerweile mehrere Compiler, keine Ahnung, aber es gibt wahrscheinlich den Standard-Compiler, den jeder verwendet. Und dort ist es natürlich relativ einheitlich. Bei JavaScript läufst du immer in einer anderen Engine, in einem anderen Browser und kannst damit gar nicht wissen, dass das überall funktioniert. Und das ist ja immer so diese Schwierigkeit mit JavaScript. Und bei JSON sind wir dann auch noch außerhalb von JavaScript. JSON-Implementierungen gibt es in jeder Sprache, in Python, in Go. Und wie die dann agieren und funktionieren, ist ja wieder eine andere Sache. Das ist immer super schwierig bei diesen allgemeingültigen Standards und die vielleicht auch gar nicht hundertprozentig definiert sind, weil keine Ahnung, ob jetzt JSON an sich das Format genau definiert, was das für ein Datentyp überhaupt ist und wie viel Bit der hat oder Byte der hat zur Repräsentation.

Andy Grunwald (00:24:52 - 00:26:16) Teilen

Ja, ich spreche natürlich eins zu eins von der Umsetzung des Parsing-Standards. Also wie sollst du welchen Wert betrachten und behandeln? Und auch die Runtime-Engines von JavaScript in den Browsern vereinheitlichen sich da mehr und mehr. Also die V8 von Google, die ist ja mehr und mehr in diversen Browsern drin oder WebKit oder ähnliches. Aber auf jeden Fall ist es auch so, dass, wir hatten ja vorhin gesagt, JavaScript selbst hat keinen Integer-Datentyp, sondern nur einen Number-Datentyp, was dann wiederum ein Float ist. Das führt natürlich dazu, dass JSON-Parser in anderen Sprachen Zahlen ebenfalls so behandelt, als wenn sie Floats wären. Das macht ja schon irgendwie Sinn, weil JSON heißt ja JavaScript Object Notation. Also scheint es ja schon sinnvoll, die Werte so zu dekodieren, wie es JavaScript machen würde. Das führt aber auch dazu, dass der Python-Build in JSON-Parser zum Beispiel Probleme mit großen Integer bekommt, weil wenn diese große Zahl aus JSON geparst wird in eine native Python-Repräsentation, dann wird sie intern als float behandelt und nicht als Integer. Und das führt natürlich dann bei großen Zahlen zu Ungenauigkeiten, wie der Wolfgang schon sagte. Also alles schon sehr, sehr schwierig und da muss man ganz, ganz, ganz, ganz genau aufpassen, wie die JSON-Parsing-Implementation sich da verhält. Also im Endeffekt verhält sich die JSON-Parsing-Repräsentation richtig, so wie es JavaScript machen würde, wenn man JSON nutzen würde.

Wolfi Gassler (00:26:17 - 00:26:50) Teilen

Man muss eben als Programmierer in einer anderen Programmiersprache, wenn man zum Beispiel mit JSON hantiert, eben auch wissen, was da dahinter steckt, damit man diese ganzen Datentypen und Nummern richtig verwendet, wenn man zum Beispiel in JSON importiert. Und da traue ich mich fast zu wetten, dass das ganz viele Nicht-JavaScript-Entwickler oder sogar JavaScript-Entwickler nicht so am Schirm haben. Und ehrlich gesagt, ich hatte das auch nicht am Schirm. Ich habe es mal irgendwo gelesen, aber das vergisst man wieder und im Alltag braucht man das ja nie, bis man dann in den Bug reinläuft. Also in einem Bug, den man dann selber produziert hat aufgrund der Repräsentation von Nummern.

Andy Grunwald (00:26:50 - 00:27:03) Teilen

Und wenn wir schon bei Floats sind, beziehungsweise von Integerwerten, die intern als Fließkommazahlen repräsentiert werden, dann kommt immer ein sehr prominentes Beispiel in meinen Kopf und zwar sind das Währungsbeträge.

Wolfi Gassler (00:27:04 - 00:27:15) Teilen

Was ist das Problem mit Währungen? Bei mir sind es immer sehr kleine Zahlen, die da auf meinem Bankkonto stehen, da gibt es keine Rundungsfehler. Aber Andi, in deinem Fall, wenn man so ganz große Zahlen hat, was gibt es da für Probleme?

Andy Grunwald (00:27:15 - 00:27:36) Teilen

Die Größe der Zahl ist erstmal irrelevant, denn auch bei 10,52 Dollar kann es zu Rundungsfehlern kommen, was dann im Endeffekt zu 10,51 Dollar oder 10,53 Dollar resultiert. Jetzt sagst du, das ist ja nur ein Cent. Frag doch mal das Finanzamt oder frag doch mal die Anzahl der Transaktionen, die durch deinen Shop gehen, wie relevant denn dieser eine Cent wird.

Wolfi Gassler (00:27:36 - 00:30:18) Teilen

Ich habe mal vor Jahrzehnten ist es schon fast ein Shop programmiert, also schon mit einem Shop-System, aber ich habe da customised einen Preisberechner rein programmiert, der Gewichtsware berechnet. Also so, was man zum Beispiel aus dem Supermarkt kennt oder so, wenn du Obst abwiegst, dann gibt es da einen Kilopreis und dann je nach Gewicht wird das dann umgerechnet. Also sowas in der Richtung, so Gewichtsfahre. Und ich hatte da wirklich dieses Problem, ich habe diese Preise von der Schnittstelle bekommen. Da fängt sich schon mal wieder an. War das JSON? Was ist das für ein Format? Ihr habt das von irgendeiner Schnittstelle bekommen, habt dann angefangen herumzurechnen selbst, diese Gewichtspreise herumzurechnen und habt es dann wieder mit einer anderen API abgleichen müssen bzw. habt ihr dann wieder Bestätigungen zurückbekommen für einen Auftrag usw. Und ich bin fast verzweifelt mit dem ganzen Ding, weil diese Rückmeldungen von einer Bestätigung von einem Auftrag waren wieder andere Preise, weil dieses System irgendwie anders gerechnet hat. Das heißt, da war dann statt 3,50 Euro habe ich plötzlich 3,52 Euro zurückbekommen, weil das System irgendwie anders gerechnet hat. Und wenn du viel dividierst oder multiplizierst, dann hast du genau diese ganzen Ungenauigkeiten und Probleme, Und hast dann wirklich bei so einem kleinen Betrag auch unter Umständen 2 Cent Unterschied, der natürlich schon relevant ist. Und wenn du mit verschiedenen Systemen zusammenarbeitest, dann hast du auch keinen Einfluss darauf. Also das ist extrem schwierig, da wirklich einen guten Ansatz zu finden, wenn du mit verschiedenen Systemen arbeitest. Wenn du natürlich nur selbst das System baust, dann kannst du bei Währungen eigentlich recht easy damit umgehen, indem du keine Floats verwendest, also keine 3,50€ als 3,50€ in dem Float oder Double abspeicherst, sondern das Ganze in den Integer umwandelst. Das heißt die 3,50€ werden umgewandelt in 350 und die 350 speicherst du dann als Integer ab, beziehungsweise im Idealfall oder sinnvollerweise rechnest du das dann auf auf Cent um, weil es ja eine sinnvolle Größe ist, oder vielleicht auf Zehntelcent, wenn du unbedingt willst. Das heißt, du multiplizierst das mal 1000 und hast dann 3500 z.B. für 3,50€ und dann arbeitest du nur in dem Integer-Feld und hast weniger Probleme, solange du nicht dividierst. weil da kommst du sofort wieder in den Gleitkommabereich rein und wenn du jetzt zum Beispiel irgendwelche Gewichtswaren berechnest und dir irgendwie einen Grammpreis oder so über Division ausrechnest, dann hast du schon wieder ein Problem. Also sobald du eine Division drin hast, bist du sofort wieder weg mit der Genauigkeit. Aber üblicherweise im Bankwesen oder wenn du mit Geld arbeitest, hast du ja nur Plus und Minus im Idealfall und dann bist du sicher, solange du im Integer-Bereich bleibst.

Andy Grunwald (00:30:18 - 00:30:26) Teilen

Und warum multipliziere ich 3,50 Euro mit 1000 und nicht mit 100? Also warum nehme ich eine dritte Nachkommastelle dazu?

Wolfi Gassler (00:30:27 - 00:30:55) Teilen

Dadurch, wenn du zum Beispiel dividierst oder die Preise jetzt zum Beispiel auf irgendein Gewicht umrechnest, hast du dann eine höhere Präzision und kannst damit noch eine höhere Präzision erreichen. Und meines Wissens, Banken arbeiten auch mit Zehntelcent, wenn ich das jetzt richtig im Kopf habe. Falls jemand im Bankwesen arbeitet, bitte gern um Rückmeldung. Aber hat eben mal so im Kopf, dass man da unter Umständen noch eine höhere Präzision haben will, um da auch nochmal gewisse Rundungsfehler zu vermeiden.

Andy Grunwald (00:30:55 - 00:31:27) Teilen

Besonders bei der Handhabung von Währungsbeträgen merkt man halt, dass Gleitkommararithmetik Rundungsfehler verursachen kann. Eine Gleitkommarzahl ist eine annähernde Darstellung eines Dezimalwerts, der binär gespeichert wird und somit ist es nicht möglich 0,1 präzise und exakt darzustellen, was dann natürlich speziell im Bereich Geld eine sehr schwierige Geschichte wird. Besonders wenn man Millionen von Transaktionen hat, weil dann kommen nämlich, dann multipliziert sich halt auch ein Rundungsfehler-Cent schon sehr hoch.

Wolfi Gassler (00:31:27 - 00:32:11) Teilen

Im Datenbankbereich hat sich das übrigens so durchgesetzt, dass man dann einen eigenen Datentyp hat, der Decimal oder Dezimal heißt und da gibt man wirklich an, wie viele Stellen will man vor diesem Komma und wie viele Stellen will man nach dem Komma speichern und dann werden die Zahlen wirklich als Integer-Zahlen jeweils abgespeichert. Das heißt, ich kann da genau selbst definieren, was für eine Genauigkeit will ich haben. Ich kann dieses Komma auch verschieben. Das heißt, wenn ich weiß, dass ich ganz kleine Zahlen immer habe und vor meinem Komma eigentlich immer nur zwei Zahlen, zwei Ziffern habe, dann kann ich das dort auch drin definieren und kann mir hinten dann wieder eine höhere Genauigkeit rausholen. Also der wandelt das dann intern sozusagen wieder auf eine, wenn man so will, auf eine Integer-Repräsentation, auf eine Ganzzahl-Repräsentation um.

Andy Grunwald (00:32:11 - 00:32:29) Teilen

Also die Faustregel ist hier niemals eine Währung als Float in der Datenbank abspeichern, nämlich die große Internet-Empfehlung ist, dass man sie als Dezimal mit vier Nachkommastellen präzise abspeichert, weil wenn man nämlich die Nachkommastellen definiert, dann kommt es da auch nicht so zu Rundungsfehlern, weil man die ganze Sache begrenzt.

Wolfi Gassler (00:32:30 - 00:32:49) Teilen

Ich glaube sogar, dass Float und Double mittlerweile auch anders gehandhabt wird, in MySQL zumindest, und die auch in so eine Repräsentation übergehen. Ich glaube, man kann die klassische Gleitkomma-Darstellung, bin mir gar nicht sicher, ob man die überhaupt noch so machen kann in der MySQL-Datenbank. hat sich auch einiges geändert.

Andy Grunwald (00:32:49 - 00:32:53) Teilen

Der MS-SQL-Server von Microsoft hat sogar einen eigenen Datentypen, Money und Small Money.

Wolfi Gassler (00:32:54 - 00:32:56) Teilen

Ha, was ist denn Small Money? Das klingt super.

Andy Grunwald (00:32:56 - 00:33:00) Teilen

Anscheinend die Geldbeträge, mit denen du hantierst, Wolfgang. Small Money.

Wolfi Gassler (00:33:00 - 00:33:02) Teilen

Von den normalsterblichen, ja.

Andy Grunwald (00:33:02 - 00:33:14) Teilen

Also laut Internet wird die ganze Sache dann aber auch als BigInt auf der Festplatte gespeichert. Deswegen sagt man auch generell, okay, nutzt mal ein Dezimal, 19.4, und dann seid ihr da einigermaßen.

Wolfi Gassler (00:33:15 - 00:35:30) Teilen

Und was übrigens auch noch so ein großes Problem ist und was ich zuerst erwähnt habe, auch wenn man mit anderen Systemen arbeitet. Ich hatte gerade gestern eine Episode von unserem befreundeten Index-Out-of-Bounds-Podcast gehört und die haben gesprochen über fremden Code und wie man mit fremden Code arbeitet und wie schwierig das ist. Und auch da wieder, Libraries sind ja auch fremder Code, wenn man so will, aber auch wenn man mit anderen Leuten zusammenarbeitet. Das ist natürlich halt extrem relevant, wenn es dann um solche Dinge geht. wie handhabt denn dieser fremde Code oder nur diese Funktion diese Datentypen und welche Berechnung kommt da zum Einsatz. Also in Shop-Systemen ist es teilweise so, dass du gar kein Plus und Minus verwendest, sondern es gibt eigene Funktionen in dem Shop-System, die Add oder Sub oder so heißen und da kannst du dann zentral festlegen, wie mit Datentypen umgegangen wird, damit du das eben zentral hast und überall gültig hast. Und wenn du mit anderen Leuten zusammenarbeitest oder mit anderem Code, mit anderen Libraries, dann musst du dir natürlich sicher sein, was passiert da. Und wenn wir dann in Skriptsprachen sind, in JavaScript, PHP oder was auch immer, dann werden da ja auch Datentypen einfach so hin und her konvertiert, ohne dass man was weiß, umgecastet. Und da läuft man natürlich dann auch gern in Probleme. Du irgendeine Library verwendest und du denkst dir, die macht irgendwie coole Berechnungen mit deinem Preis und da geht es um Euro und du verlierst dann die Präzision in dieser Library, dann hast du natürlich auch ein Problem und das musst du dir auch bewusst sein. Oder wenn du zum Beispiel in SQL was berechnest, so wie ich am Anfang erwähnt habe, wenn du eine Division in SQL machst, was wird denn dann da verwendet für diese Division? Wird dann float, double, new decimal, was für ein decimal verwendet? Also auch da, das läuft ja transparent im Hintergrund ab, ohne dass man das mitbekommt. Und da können sich extrem leicht Fehler einschleichen. Aber man kann es natürlich auch zum Vorteil verwenden. Ich weiß nicht, ob du diese Geschichte kennst. Diese Entwickler, die sich dann im Bankenbereich immer diese Rundungsfehler selber abgesaugt haben, da wo gerundet wird, und haben sich dann das auf ihr eigenes Konto überwiesen, was die Bank so verliert durchs Runden. Und am Ende sind die mit sehr, sehr viel Geld ausgestiegen, weil sie sich einfach diese mini, mini, mini Beträge sich einfach rausgeholt haben aus dem System. Können wir gern verlinken, wenn ich die Geschichte nochmal finde.

Andy Grunwald (00:35:31 - 00:35:46) Teilen

Wolfgang, jetzt testen wir auch mal dein Wissen. Quizfrage. Was passiert denn, wenn ich auf einem Integer, der kein Vorzeichen repräsentiert, also unsigned Integer, ein 0-1 mache, wenn ich versuche in den negativen Bereich zu gehen, bei einem nicht vorzeitig behafteten Integer?

Wolfi Gassler (00:35:46 - 00:35:55) Teilen

In welcher Programmiersprache oder SQL oder Excel? Wo mache ich denn das? In der Bash? Kann Bash überhaupt zahlen? Anderes Thema.

Andy Grunwald (00:35:55 - 00:35:56) Teilen

Gibt es da Unterschiede?

Wolfi Gassler (00:35:56 - 00:36:39) Teilen

Ja, das ist die Informatikerantwort. Wenn du keine Ahnung hast, dann stellst du mal eine Gegenfrage, in was für einem Kontext man sich denn da befindet. Das ist immer ganz, ganz wichtig. Du bist ja auch so ein Kontext-Fan. Darum kann man sich immer auf die Programmiersprache rausreden. Weil ich bin mir fast sicher, dass das jede Programmiersprache anders handhabt. Also wenn man das in PHP macht, gut, da gibt's kein Unsigned, das ich fix setzen kann, höchstwahrscheinlich. Da würde mir wahrscheinlich irgendwas umkommodieren, dieser Interpreter, und dann irgendein Mull-Asch-Bucken. Wenn du das in C machst, ganz klassisch, da bekommt man dann wahrscheinlich irgendeine ganz große Zahl, minus 40 Millionen irgendwas. Da gibt's wahrscheinlich sicher irgendeinen Underflow, Overflow, irgendeinen Flow, vermute ich mal. Das sind so die Klassiker, wo man sich selber ins Knie schießt in C.

Andy Grunwald (00:36:39 - 00:36:44) Teilen

Also was ganz klar ist, man bekommt auf keinen Fall nicht minus 1 raus, weil man hat ja keinen Minuswertebereich.

Wolfi Gassler (00:36:44 - 00:36:53) Teilen

Vielleicht nur zur Vollständigkeit. Was ich mir erwarten würde, ist ein Fehler. Das heißt, dass ich irgendwo einen Fehler bekomme, hey, ich mach da was Unerlaubtes. Das wäre ja eigentlich das Schöne.

Andy Grunwald (00:36:53 - 00:37:22) Teilen

Ja, und da kommen wir jetzt in diesem Es-ist-kompliziert-Bereich. Also, es ist wirklich so, wenn du bei einer Sprache unterwegs bist, die Unsigned-Integer-Datentypen hat, das ist ja die erste Baustelle, dann kriegst du bei einem 0-1 in der Regel den Overflow und es fängt dann ganz oben wieder an. Ja, so nach dem Motto, du bist ja erst in der Schlange und stellst dich bei der Achterbahn ganz hinten wieder an. Somit bist du der letzte in der Schlange, somit kriegst du den höchsten Wertebereich, die höchstmögliche Zahl aus dem Wertebereich. Jetzt ist es doch nun mal so.

Wolfi Gassler (00:37:22 - 00:37:31) Teilen

Super, jetzt denke ich ständig an diese Achterbahn und ich verstehe die Lösung nicht einmal mehr. Also Achterbahn ist definitiv ein schlechtes Beispiel, um mir das zumindest zu erklären.

Andy Grunwald (00:37:32 - 00:37:41) Teilen

Also wenn du auf einem Uint32, also auf einem Unsigned Integer mit 32 Bit ein 0-1 machst, dann ist das Ergebnis eine 10-stellige Zahl.

Wolfi Gassler (00:37:41 - 00:37:44) Teilen

Ja, da bekommst du wahrscheinlich das Maximum-1, oder?

Andy Grunwald (00:37:44 - 00:37:50) Teilen

Theoretisch ja, oder halt genau das Maximum. Aber das ist dieser Off-by-one-Error, von dem wir immer reden.

Wolfi Gassler (00:37:50 - 00:37:53) Teilen

Aber ist egal. Da sprechen wir gar nicht drüber.

Andy Grunwald (00:37:53 - 00:38:12) Teilen

Aber der Clou ist ja, hat deine Programmiersprache überhaupt einen Unsigned Integer? Weil, das Lustige ist eigentlich, Python zum Beispiel hat keine built-in Unsigned Integer Datentypen. Java hat auch keine built-in Unsigned Integer Datentypen. Es gibt eine Integer Class, die kann das. aber der native datentyp ist nicht existent.

Wolfi Gassler (00:38:12 - 00:38:22) Teilen

Und du bekommst dann auch einen underflow wenn du bei java sowas machst also es gibt gar keinen unsigned das heißt du kannst gar nicht zwingend machen du bekommst dann trotzdem den minuswert ganz genau.

Andy Grunwald (00:38:22 - 00:38:49) Teilen

Ruby ist ganz geil weil ruby Einfach zwischen den Datentypen hin und her konvertiert und der ganze Prozess ist sehr transparent. Das bedeutet auch wenn du sagst du möchtest 32 oder 8 Bit Integer und du packst da eine ganz große Zahl rein, dann konvertiert der intern automatisch zu einer Big Num. Ich weiß nicht ganz ob das geil ist oder ob ich das schrecklich finde. Ich habe mir da noch keine Meinung drüber gebildet. Es ist auf jeden Fall so ein bisschen Magie wie Ruby halt auch so ist, finde ich.

Wolfi Gassler (00:38:49 - 00:39:29) Teilen

Man muss ja auch dazu sagen, warum das Ganze meistens so schwierig ist und keine Fehlermeldungen ausspuckt, ist da, dass wir da über native Datentypen sprechen, die meistens einfach nicht gecheckt werden, weil es sind halt sehr rudimentäre Operationen und wenn du da noch irgendwelche komplizierten Checks einbaust, dann kann es natürlich sein, dass du auch Performance-Probleme bekommst. Aber theoretisch wäre es ja kein Problem, das einzubauen. Und wie du richtig sagst, wenn du eine Klasse machst, die das alles checkt, könntest du das natürlich genauso machen. Aber du bläst deine Sprache natürlich schon extrem auf damit. Und ich vermute mal, ohne jetzt ein Sprachdesigner zu sein, dass das schon ein Grund ist, warum das teilweise so dreckig, würde ich mal sagen, gehandhabt wird.

Andy Grunwald (00:39:29 - 00:39:42) Teilen

Du kannst dich halt, wenn du eine Sprache designst, auf den Standpunkt stellen, okay, der Programmierer muss schon wissen, was er da tut. Deswegen, du kannst halt die Arbeit auf den Programmierer abwälzen. Und genau das haben sie bei C gemacht. Wenn du C programmierst, der C wälzt.

Wolfi Gassler (00:39:42 - 00:39:45) Teilen

Alles auf die auf die Programmierer ab. Da gibt es überhaupt nichts.

Andy Grunwald (00:39:46 - 00:39:55) Teilen

In der C-Programmierer-Sprache, Wird die ganze Thematik einfach mitgehändelt? Das bedeutet, du merkst gar nicht, dass du einen Overflow hast. Und das kann natürlich zu richtigen Bugs führen.

Wolfi Gassler (00:39:55 - 00:40:01) Teilen

Also es wird nicht gehändelt, sondern es macht halt einfach nichts. Es zählt nach unten und du bekommst halt eine große Zahl oder so.

Andy Grunwald (00:40:01 - 00:40:05) Teilen

Ja, also es wird halt schon gehändelt, weil das Programm läuft einfach weiter. Es crasht nicht.

Wolfi Gassler (00:40:05 - 00:40:09) Teilen

Ja, es ist halt nach, so wie es definiert ist mathematisch, wird einfach durchgezogen, ja.

Andy Grunwald (00:40:10 - 00:40:55) Teilen

Ja, ob es jetzt im ursprünglichen C-Standard als so soll das sein definiert ist, weiß ich jetzt nicht. Auf jeden Fall gibt es bei CLang, beim CLang-Compiler jetzt ein Compiler-Flag, was unter der Kategorie Undefined Behavior geführt wird. Und da kannst du sagen, okay, wenn du mein C-Programm kompilierst und wir haben ein Integer Under oder Overflow, dann lass das C-Programm bitte abstürzen. Der Grund ist, dass es nicht undefined behavior ist, aber es ist sehr oft nicht gewollt. Also ich kenne keinen Softwareentwickler, der sagt, okay, pass mal auf, ich möchte jetzt hier, dass mein Integer overflowed oder underflowed. Aber jetzt haben wir hier über dieses Integer underflow und overflow gesprochen, jetzt jeder denkt sich, ach Quatsch, mit so vielen Zahlen arbeite ich gar nicht. Wo kommt denn der ganze Quatsch mal in der Realität vor? Wo hast du sowas schon mal gesehen oder wo denkst du, kriegen wir nochmal richtig Probleme?

Wolfi Gassler (00:40:56 - 00:41:14) Teilen

Ja, jetzt könnte man natürlich wieder dieses Jahr 2038-Problem erwähnen, das wir eh schon ständig erwähnt haben und was wahrscheinlich mittlerweile eh jeder kennt, der irgendwie mit Unix-Timestamps zu tun hat, dass im Jahr 2038 die Unix-Timestamps überlaufen, wenn man 32-Bit speichert und dann ein großes Problem haben wird. Aber, Andi, kennst du das 2036-Problem?

Andy Grunwald (00:41:16 - 00:41:20) Teilen

Ja, kenne ich. Und ich kannte es vor der Vorbereitung des Podcasts auch noch nicht.

Wolfi Gassler (00:41:20 - 00:41:27) Teilen

Ja, ich natürlich auch nicht. Ich habe es nur in unseren Notes ganz intelligent, ohne eine Ahnung zu haben, was eigentlich dahinter steckt.

Andy Grunwald (00:41:27 - 00:41:58) Teilen

Das nochmal zum Recap. Das Jahr 2038 Problem hat mit der UNIX-Zeit zu tun, mit dem UNIX-Timestamp. Der beginnt am 01.01.1970. Die Speicherung dessen in einem 32-Bit-Integer führt zu einem Integer Overflow am 19. Januar 2038, was dann die Zeit durch den Overflow auf den 13. Dezember 1901 zurückführt, wenn man das jetzt wieder in Zeit berechnen würde. Jetzt gibt es aber auch noch das Jahr 2036 Problem.

Wolfi Gassler (00:41:58 - 00:42:04) Teilen

Warum eigentlich 1901? Müsste es nicht 1970 sein? Die Unix Timestamp fängt ja 1970 zählen an.

Andy Grunwald (00:42:05 - 00:42:20) Teilen

Gut aufgepasst Wolfgang, aber wir reden von einem Signed Integer 32. Das bedeutet, wir gehen vom Maximum des positiven Wertebereichs ins Maximum des negativen Wertebereichs und deswegen sind wir bei Minus eine ganz lange Zahl.

Wolfi Gassler (00:42:20 - 00:42:44) Teilen

Das heißt ungefähr kann man in einem Range 70 Jahre abbilden, oder? Das heißt 70, 140, 2038, das kommt ungefähr hin. Also im Minusbereich 70 Jahre und im positiven Bereich 70 Jahre. Wenn man das jetzt aber, also man kann es nicht rückwirkend machen, aber wenn man, doch man könnte eigentlich definieren in Zukunft, wenn der Bereich Minus ist, dann shiftet das Ganze, dann könnt ihr nochmal 70 Jahre rausholen.

Andy Grunwald (00:42:44 - 00:42:51) Teilen

Das ist korrekt, dafür ist aber eine Softwareänderung notwendig und da kannst du das Problem gleich fixen und dann ins 64 nehmen, oder?

Wolfi Gassler (00:42:51 - 00:42:59) Teilen

Ich bin gegen diese guten Lösungen, die dann langfristig laufen. Ich würde da nochmal 70 Jahre herausholen. Die Mainframes machen das sicher auch so.

Andy Grunwald (00:42:59 - 00:43:13) Teilen

Aber das viel spannendere Problem ist das 2036 Problem. Das 2038 Problem haben wir gerade erklärt und ist groß und breit in der Industrie vertreten. Das Jahr 2036 Problem ist glaube ich deutlich subtiler und zwar dreht sich das um Das Zeitsynchronisationsprotokoll NTP.

Wolfi Gassler (00:43:13 - 00:43:18) Teilen

Verwende ich auf allen meinen Servern natürlich. Hätte es dann 2036 aufzuarbeiten?

Andy Grunwald (00:43:18 - 00:43:50) Teilen

Die Startzeit vom Zeitsynchronisationsprotokoll NTP ist nicht der 01.01.1970. Die Startzeit ist der 01.01.1900. In älteren NTP-Implementierungen wurde was verwendet? Ein Integer 32. Das bedeutet, auf allen Devices, wo eine ältere NTP-Version installiert ist, wird nochmal ein Integer 32 gearbeitet, was bei der Zeit 01.01.1900 anfängt zu zählen. Der Überlauf ist am 07.02.2036.

Wolfi Gassler (00:43:50 - 00:43:53) Teilen

Aber von welchen Implementierungen sprechen wir da, von wirklich alten?

Andy Grunwald (00:43:53 - 00:44:13) Teilen

Mit hoher Wahrscheinlichkeit sind moderne Cloud-Server nicht betroffen, sondern eher Embedded-Systeme, die in irgendwelchen Stahlwerken oder ähnliches verbaut werden, die seit Ewigkeiten nicht geupdatet werden. Wir reden hier von den Computern, Chipsystemen, die in irgendeiner Ecke von irgendeiner großen Firma stehen und die Staub fangen und die einfach laufen, die keiner auf dem Schirm hat.

Wolfi Gassler (00:44:13 - 00:44:26) Teilen

Und die springen dann auf 1900 zurück, demnach, oder? Wenn sie dann einen Overflow haben. Die Frage ist, ob dem Stahlwerk das nicht egal ist. Die leben vielleicht dann einfach 1900 weiter. Also dieses Ding kommuniziert mit anderen Systemen. Dann wird es schwierig.

Andy Grunwald (00:44:26 - 00:44:40) Teilen

Die springen auf den 1.1.1900 zurück, weil sie eine nicht vorzeichenbehaftete Integer 32 Implementierung genutzt haben und keine vorzeichenbehaftete wie bei dem Jahr 2038 Problem. Ja, spannende Zeiten kommen auf uns zu, würde ich sagen.

Wolfi Gassler (00:44:40 - 00:44:42) Teilen

Naja, noch haben wir 10 Jahre, über 10 Jahre.

Andy Grunwald (00:44:42 - 00:44:51) Teilen

Und wenn wir gerade bei Zeit sind, wie oft würdest du dir wünschen, dass Zeit rückwärts laufen kann, Wolfgang? Dass du Sachen nochmal erleben kannst, dass du Sachen korrigieren kannst.

Wolfi Gassler (00:44:52 - 00:44:54) Teilen

Ganz allgemein oder wie oft ich mir das heute schon gewünscht hätte?

Andy Grunwald (00:44:54 - 00:44:57) Teilen

Kannst du eigentlich eine Frage beantworten ohne eine Gegenfrage zu bestellen?

Wolfi Gassler (00:44:57 - 00:45:04) Teilen

Siehst du, jetzt wäre ich gern wieder in die Vergangenheit gereist und hätte dir eine dumme Frage gestellt noch, eine andere. Aber warum? Kannst du das?

Andy Grunwald (00:45:04 - 00:45:14) Teilen

Ich kann es nicht, aber in der IT passiert das öfter. Und die meisten Softwareentwickler wissen das nicht oder bauen das nicht ein. Wolfgang, erklär uns doch mal bitte, wann kann die Zeit rückwärts laufen?

Wolfi Gassler (00:45:15 - 00:45:21) Teilen

Ja, dein Beispiel mit dem 2036-Problem war ja im Prinzip schon rückwärts laufen. Wir springen da wieder auf 1900 zurück, oder?

Andy Grunwald (00:45:21 - 00:46:00) Teilen

Ja, das ist richtig. Das ist aber eine andere Problemklasse. Da reden wir über Integer Overflow. Und man muss ja auch sagen, okay, wenn die Zeit rückwärts laufen kann, das ist nicht wirklich ein Problem mit Zahlen, sondern es wird halt oft in der Programmierung genutzt, sondern es ist eher ein Problem mit der realen Implementierung, was man da benutzt. In klassischen Implementierungen ist es eigentlich so, dass man die aktuelle Zeit erhebt, um irgendwas zu messen. Zum Beispiel die Zeit zwischen zwei Events oder... Man nutzt die Zeit, auf jeden Fall die aktuelle Zeit, also den 13. März, 9.53 Uhr, um diesen Wert mit irgendwas zu vergleichen. Und man geht von der Annahme aus, dass Zeit immer nur in eine Richtung geht, immer vorwärts.

Wolfi Gassler (00:46:01 - 00:46:04) Teilen

Also meine Zeit geht immer vorwärts. Ich weiß nicht, wie deine Zeit so ist.

Andy Grunwald (00:46:04 - 00:46:57) Teilen

Dann nutzt du, glaube ich, andere Computer oder lebst auf einer anderen Erde als ich. Weil Zeit läuft eigentlich nicht immer vorwärts. Und zwar gibt es die sogenannte Leap Second. Leute, die schon länger in der Informatik sind, haben davon schon mal gehört. Leute, die irgendwie erst neuerdings mit modernen Linux-Körneln und so weiter und so fort zu tun haben, da ist das kein Thema mehr, weil Linux das inzwischen ganz gut abfangen kann. Aber früher hat das immer zu sehr komischen Problemen geführt. Was ist die Leap Second? Und zwar geht es um die Erde, um die Planeten auf denen wir leben. Die Erde bei ihrer Drehung um sich selbst benötigt im Mittel etwas länger als 24 Stunden. Das bedeutet die mittlere Eigenrotation der Erde ist zu langsam. Das bedeutet, zur Korrektur der Abweichung der koordinierten Weltzeit wird ab und zu mal eine Sekunde abgezogen, glaube ich, oder? Ja, abgezogen wird die, weil der liebst hängt.

Wolfi Gassler (00:46:57 - 00:47:53) Teilen

Ich vermute mal schon, aber meine Frage stellt sich ja immer, das ist ja nicht irgendwann, das ist ja nicht wahllos, dass da irgendwo eine Sekunde wegfällt, sondern das ist ja ein ganz genau definierter Zeitpunkt, wann diese Sekunde wegfällt. Das ist ja so wie im Februar. Du hast gemerkt, ich habe schon Februar gesagt, weil Februar würdest du schon wieder nicht verstehen, die österreichische Variante. Also der Februar, der hat ja hin und wieder einen Tag weniger in dem Schaltjahr. Und das ist ja eigentlich das gleiche Konzept. Und alle Date Libraries, wenn ich jetzt am 1. März ausrechnen will, wie viele Tage sind vergangen zum 27., dann bekomme ich da ja normalerweise das richtige Ergebnis raus. Das heißt, meine Date Libraries machen das mir schon richtig. Das heißt, eigentlich könnten die das ja bei der Sekunde auch machen, weil die ganz genau wissen, wo diese Sekunde verloren geht. Nur scheinbar machen das diese Date Libraries nicht, vermute ich mal. Also du bist wahrscheinlich in einem hochspezialisierten Bereich, vielleicht wird es da angewandt.

Andy Grunwald (00:47:53 - 00:48:29) Teilen

Also ich kenne keine Date Implementierung, die die Leap Second Events mit kalkuliert, aber das ist der eine Fall. Es gibt aber auch der andere Fall, dass einfach die Zeit auf deinem Server, auf dem du deine Software laufen lässt, einfach rekonfiguriert wird. Zum Beispiel, weil der NTP-Server, mit dem es kommuniziert, einfach nicht mehr gibt. Dann hast du auf jeden Fall einen Timedrift und irgendwann kommt der Admin vorbei und sagt, hey, die Zeit ist ja falsch, ich konfiguriere die einfach mal. Oder deine lokale Serverzeit ist auf deine Zeitzone eingestellt und deine lokale Serverzeit läuft nicht auf UTC. Aber dein Programm hat keine UTC-Umberechnung mit einprogrammiert und puffs, springst du einfach mal Zeit zurück, wenn du in UTC plus irgendwas bist.

Wolfi Gassler (00:48:30 - 00:48:41) Teilen

So und jetzt kommt dann meine Killerfrage, wenn du jetzt schon der Leap Second Spezialist bist. Was ist mit der Unix Timestamp? Die zählt ja in Sekunden. Zählt dir die Leap Second mit oder nicht?

Andy Grunwald (00:48:41 - 00:49:04) Teilen

Sehr gute Frage. Ich kenne die Antwort nicht ganz genau, aber ich würde mir sie mal herleiten. Da die Unix Timestamp ja eigentlich von der Wall Clock genommen wird, müsste der die eigentlich mitzählen. Weil die World Clock ist ja die aktuelle Zeit auf dem Server, in der wir uns bewegen. Und davon holt die sich die Unix Timestamp. Und wenn die aktuelle Zeit einfach eine Sekunde zurückspringt, dann müsste die Unix, der Unix Timestamp, die eigentlich mitzählen.

Wolfi Gassler (00:49:04 - 00:49:28) Teilen

Ihr habt natürlich in der Zwischenzeit schnell gegoogelt und so wie das aussieht, hat die Unix Timestamps keine Leap Seconds, weil sie immer gesyncht ist mit UTC. Also genau so, wie du es jetzt hergeleitet hast. würde ich mal als richtig bezeichnen, sonst wird sich unsere nette Community, unsere Hörerschaft garantiert bei uns melden, so wie mit 200 anderen Dingen, die wir wahrscheinlich heute irgendwie leicht fälschlich erwähnt haben. Wir freuen uns schon auf das Feedback.

Andy Grunwald (00:49:28 - 00:49:57) Teilen

Aber generell reden wir hier natürlich von einer gewissen Zeit, und zwar reden wir von der Wall Clock Time, die unerwartet zurück- beziehungsweise vorspringen kann. Und in der Programmierung, habe ich gerade schon erwähnt, wird sie oft genutzt, um die Dauer von zwei Punkten zu messen oder um alle x Sekunden einen Prozess zu starten, wie zum Beispiel einen Ticker oder einen Timer. Jetzt stellt sich natürlich die große Frage, Wolfgang, wie baue ich das denn richtig? Zeitberechnung, Datumsberechnung und Co. ist ja einer der drei, vier, fünf harten Elemente der Softwareentwicklung. Also wie schütze ich mich vor zurücklaufenden Uhrzeiten?

Wolfi Gassler (00:49:58 - 00:50:54) Teilen

Ja, du hast ja üblicherweise mehrere Möglichkeiten auf Zeit zuzugreifen und die klassische ist einfach auf die Systemzeit zuzugreifen, also wirklich auf die Zeit mit Datum und so weiter. Oder du kannst halt einfach mitzählen und die Monotonic Clock verwenden, die halt einfach am Server mitzählt. ohne zu wissen, was jetzt genau für ein Datum ist und die kannst du dann verwenden, die mitzählende Uhr, um zum Beispiel die Sekunden einfach zu berechnen, wenn dir die so kritisch wichtig sind natürlich. Für die meisten Anwendungsfälle muss man ja auch sagen, wenn du irgendwo eine leap second hast und eine second vergisst, dann wird halt die Funktion vielleicht einmal mehr aufgerufen oder sowas, weil eine Sekunde verloren geht. Aber sonst kannst du natürlich ganz hart einfach diese mitzählende Uhr verwenden und dann, wenn du sagst drei Sekunden, wird einfach hart drei Sekunden mitgezählt, egal ob sich die Systemzeit jetzt ändert oder nicht. Aber ich habe ehrlich gesagt dieses Ding noch nie verwendet. Wie greife ich da in der Programmiersprache drauf zu? Habe ich da eigene Funktionen wahrscheinlich, oder?

Andy Grunwald (00:50:54 - 00:51:28) Teilen

Jede Programmiersprache hat in der Regel in der Standard Library einen Zugriff auf die Monotonic Clock, ja. Das ist einer der häufigsten Fehler, die ich in Recruiting-Case-Studies sehe, weil viele Case-Studies haben ein Element drin, ja berechne mal bitte irgendwie die Dauer, wie lange ein HTTP-Request gedauert hat. Und für solche Anwendungsfälle sollte man in der Regel einen Montoni-Clock nutzen und nicht die aktuelle Zeit, weil die aktuelle Zeit kann zurück- und vorspringen. Und wenn man da ja Subtraktionen macht, Startzeitpunkt hat der tpRequest Endzeitpunkt und dann rechnet man Endzeitpunkt minus Startzeitpunkt, Startzeitpunkt minus Endzeitpunkt.

Wolfi Gassler (00:51:28 - 00:51:35) Teilen

Endzeitpunkt minus Startzeitpunkt meinst du? Die größere Zahl minus der kleineren Zahl, ganz einfach, sagen wir mal so.

Andy Grunwald (00:51:35 - 00:51:51) Teilen

Dann rechnet man Endzeitpunkt minus Startzeitpunkt und dann bekommt man einfach eine negative Zahl raus, bei einem vorzeichneten Behafteten Integer. Ja, das wird ja alles immer komplizierter, umso mehr mit Datentypen wir sprechen. Aber für solche Elemente nutzt man eigentlich eine Motonic-Clock und nicht die aktuelle Wall-Clock.

Wolfi Gassler (00:51:51 - 00:52:05) Teilen

Wobei ich würde das jetzt vielleicht nicht gerade als Fehler bezeichnen, aber wenn man natürlich viel damit macht, könnte man natürlich auf sowas umsteigen. Aber um jetzt mal schnell zu checken, wie lange dauert irgendwie ein Request oder so, finde ich, ist das schon ausreichend.

Andy Grunwald (00:52:05 - 00:52:13) Teilen

Meines Erachtens nach ist das ein Fehler, weil wenn du nämlich die Leap Second hast, dann hast du in deinen Dashboards überall mega Spikes in den Performance-Zeiten und Co.

Wolfi Gassler (00:52:13 - 00:52:28) Teilen

Ja, ich sag ja, wenn du das regelmäßig trackst, ist es sicher sinnvoll, aber wenn du jetzt nur mal schnell während der Entwicklung irgendwas testest oder so, dann ist es meiner Meinung nach komplett ausreichend. Wenn du natürlich ganze Statistiken fährst, kann das unter Umständen schon eine Auswirkung haben, das stimmt natürlich.

Andy Grunwald (00:52:28 - 00:52:35) Teilen

Und machen wir uns mal nichts vor, ob du jetzt time.now nimmst oder time.monotonic now, also es ist ja kein großer Unterschied.

Wolfi Gassler (00:52:35 - 00:52:45) Teilen

Ja, hast du mich überzeugt. Ich werde es in Zukunft verwenden. Jetzt habe ich wieder was gelernt, Andi, sehr gut. Also ich habe ganz viel gelernt, aber was ganz Konkretes, das ich in Zukunft machen werde.

Andy Grunwald (00:52:45 - 00:53:00) Teilen

Und das nächste Problem ist wirklich, wirklich skurril. Und zwar geht es um eine Modulo-Operation. Wolfgang, ich hatte dich am Anfang der Episode gefragt, wie viel Mathematik mit der Softwareentwicklung zu tun hat. Und du hast gesagt, essentieller Part. Wie oft verwendest du die Modulo-Operation in deinem Source Code?

Wolfi Gassler (00:53:00 - 00:53:01) Teilen

Oft, sehr oft natürlich.

Andy Grunwald (00:53:02 - 00:53:03) Teilen

Was ist ein klassischer Anwendungsfall?

Wolfi Gassler (00:53:03 - 00:53:16) Teilen

Ich glaube, der Klassiker ist eigentlich immer, wenn man durch Listen öfters durchläuft und einfach immer plus 1 macht, damit man dann wieder am Anfang von dem Array anfängt mit dem Index. Das ist, glaube ich, so der Case, der mir am öftesten unterkommt.

Andy Grunwald (00:53:16 - 00:53:20) Teilen

Das bedeutet in der Regel, dass du Modulo-Operationen mit zwei positiven Zahlen machst.

Wolfi Gassler (00:53:20 - 00:53:21) Teilen

Genau.

Andy Grunwald (00:53:21 - 00:53:23) Teilen

Hast du schon mal eine Modulo-Operation mit einer negativen Zahl gemacht?

Wolfi Gassler (00:53:24 - 00:53:47) Teilen

Ja, habe ich. Und ich habe mich auch damals gefragt, was denn da eigentlich rauskommt, weil ich mir selber nicht sicher war und habe es dann in der Programmiersprache eingegeben und gecheckt, was wirklich rauskommt. Weil man kann das Ganze ja positiv rechnen, einfach dieses Vorzeichen ignorieren im positiven Space rechnen und dann wieder dieses Minus davor schreiben. Oder im mathematischen Sinn, da kommt dann was anderes raus. Also das ist gar nicht so leicht zu definieren.

Andy Grunwald (00:53:48 - 00:54:18) Teilen

Und genau darum geht es bei dieser Problemklasse. Modulo-Operationen mit negativen Zahlen. Das ist eher eine Designentscheidung der Programmiersprache, wie die einzelnen Programmiersprachen ihre mathematischen Bibliotheken gestalten. Nehmen wir mal als Beispiel minus 13 Modulo 3. Entsprachen wie Python, Lua, Haskell, Ruby und Dart kommt dort 2 raus. Entsprachen wie JavaScript, Go, PHP, Rust und Scala kommt da minus 1 raus. Und ich so, hä? Warum ist das so, Wolfgang? Ist Mathematik nicht eigentlich idempotent? Müsste Modulo nicht eigentlich immer das gleiche rauskommen?

Wolfi Gassler (00:54:18 - 00:55:32) Teilen

Ja, die klassische Division mit Rest ist meines Wissens nur für positive Zahlen definiert. Und irgendwann hat man sich halt überlegt, okay, für negative Zahlen wäre das aber auch ganz praktisch. Und ich kann jetzt natürlich von zwei Seiten rechnen. Das heißt, wenn ich jetzt minus 13 Modulo 3 rechne, ich könnte jetzt natürlich sagen, ich multipliziere diese 3 mit minus 5. 3 mal minus 5 ist minus 15 und um jetzt auf minus 13 zu kommen, addiere 2, plus 2, dann bin ich bei minus 13. Ihr könnt das natürlich aber auch anders sehen, aber ich könnte natürlich auch sagen, ich multipliziere jetzt diese 3 von meinem Modulo 3 mit minus 4, dann bin ich bei minus 12. und dann addiere ich minus 1, bin ich auch wieder bei minus 13. Das heißt einmal kann die Lösung sein plus 2 oder einmal kann die Lösung sein minus 1. Das heißt je nachdem, ob ich erlaube, dass das Resultat von meiner Modulo-Operation positiv ist oder auch negativ sein kann. Und das sind die zwei Definitionen, die in den zwei Programmiersprachen Gruppen, würde ich es mal nennen, Aber glücklicherweise hat ja ein alter Bekannter, Donald Knuth, den ja jeder, der im IT-Bereich irgendwie unterwegs ist, eigentlich kennen sollte. Warum, Andi, sollte man den kennen?

Andy Grunwald (00:55:33 - 00:55:38) Teilen

Okay, warum sollte ich jemanden, der so heißt, kennen? Warum sollte ich Donald Knuth kennen?

Wolfi Gassler (00:55:38 - 00:55:40) Teilen

Du hast ja so einen Studienabbrecher-Titel, oder?

Andy Grunwald (00:55:40 - 00:55:42) Teilen

Ja, Bachelor nennt man das, genau.

Wolfi Gassler (00:55:43 - 00:55:51) Teilen

Und du hast ja da deine Bachelor-Arbeit Ghostwriten lassen irgendwo. Dieser Ghostwriter, hat der Word verwendet oder LaTeX?

Andy Grunwald (00:55:51 - 00:56:00) Teilen

Ich hab LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX.

Wolfi Gassler (00:56:00 - 00:57:53) Teilen

LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTeX, LaTe weil dieser Donald Knuth lebt übrigens noch irgendwie glaub einsam auf einer Insel und lässt sich die E-Mails nur ausgedruckt schicken einmal im Monat, ist ein sehr bekannter Informatikprofessor, hat auch den Turing Award bekommen und wofür er eigentlich bekannt ist, ist seine ganzen Definitionen, die er im Informatikbereich gemacht hat und unter anderem hat der auch den Modulu-Operator definiert, später mal, was dort rauskommen soll. Und nach dem richten sich eigentlich auch sehr viele Programmiersprachen. Und der hat auch noch tausende andere Definitionen rausgebracht. Da gibt's die große Buchreihe, The Art of Computer Programming, von ihm. Da schreibt er immer noch dran. Ich glaube, es gibt jetzt den neunten Band oder den achten Band. Und pro Band investiert er Jahre, um da alle Definitionen im Computerbereich reinzuschreiben und Problemstellungen und von Bäumen über Graphen. Da ist wirklich jeder Algorithmus drin in diesen Büchern. Super kompakt, sehr hardcore mathematisch definiert, muss man auch sagen. Also es ist so ein klassisches Werk, das man zumindestens an jeder Uni findet und man sollte da wirklich mal reinschauen, ist wirklich impressive, was da in diesen Büchern drin steht. Ist ein sehr schrulliger Typ, man kann auch so Vorlesungen noch online anschauen, die er macht regelmäßig. Ist natürlich auch schon in die Jahre gekommen, ist jetzt 85. aber hat wirklich viel bewegt im Computerbereich und unter anderem eben auch diesen Moduloot definiert. Und damit ist der Knut auf der Python-Lua-Haskell-Ruby-Tatseite, weil der Divisor, also das Vorzeichen vom Divisor, bestimmt das Resultat, also in dem Fall man rundet ab.

Andy Grunwald (00:57:53 - 00:58:30) Teilen

So, jetzt könnte man sich natürlich hinstellen und sagen, das ist doch gar kein Problem für mich, denn ich habe meine komplette Infrastruktur in Ruby. Dann ist das ja kein Problem. Oh, warte! Was ist da hinten? Ich glaube, die Microservice-Fraktion meldet sich gerade. Da habt ihr natürlich ein klitzekleines Problem, wenn ihr ziemlich viele Modulo-Operationen macht und verschiedene Microservices habt. Einen in Python, einen in Ruby, einen in Go, einen in JavaScript. Gegebenenfalls solltet ihr da mal ein bisschen tiefer reinschauen, weil das sind Bugs. Ich bin mir nicht sicher, ob man die wirklich gut tracken kann. Also, ich glaub, das sind so klassische Bugs, die jagt man vier Tage, und dann am Ende ist es irgendwie so ein Einzeichen-Change oder so was.

Wolfi Gassler (00:58:30 - 00:58:41) Teilen

Ihr habt mir gerade überlegt, was ein gutes Beispiel wäre, wo ich eine Minuszahl-Modulo rechne, aber mir ist ehrlich gesagt gerade kein Beispiel angefallen. Obwohl ich das mal irgendwann in der Vergangenheit verwendet habe, aber keine Ahnung mehr für was.

Andy Grunwald (00:58:41 - 00:59:04) Teilen

Natürlich gibt es noch viel, viel, viel, viel mehr Probleme mit Zahlen, mit Integern und Floats. Wir haben noch gar nicht über die Portabilität zwischen 32- und 64-Bit-Architekturen gesprochen. Was passiert eigentlich mit Fehlern bei impliziter und expliziter Typ-Konversation von String nach Integer? Wie werden verschiedene Basen, Oktal, Dezimal und so weiter, damit reingerechnet?

Wolfi Gassler (00:59:04 - 00:59:17) Teilen

Und eigentlich mein Lieblingsthema in Datenbanken, was verwende ich denn für einen Primary Key? Was sind UUIDs? Wie werden UUIDs abgespeichert? Wie mache ich dieses Ganze? Also da können wir glaube ich noch eine ganze Episode füllen mit diesen Themen.

Andy Grunwald (00:59:17 - 01:00:05) Teilen

Ja, und der Klassiker bei einem Typo ist bei einer IF-Abfrage UND UND versus einen einfachen UND, wie der Wolfgang schon initial in der Episode erwähnt hatte. Ganz klassische Bit-Operationen bei einem AND oder OR. Schneller getippt, sehr hart zu finden, würde ich sagen. Wenn ihr bis hierhin durchgehalten habt, Gratulation! Ihr habt die Vorlesung bestanden. Für alle Leute, die jetzt gerade schlafen, eigentlich sollten wir jetzt mal so einen Wecker-Klingelton irgendwie einspielen, damit die ganzen Leute wach werden. Vielen Dank für's dranbleiben. Ich hoffe, das war ein bisschen interessant für euch. Ich hoffe, wenn ihr irgendwie alte Industrieanlagen habt, die NTP-Implementierung haben, wäre cool, wenn ihr die bis Jahr 2036 fixen könntet. Ich wäre euch sehr dankbar, denn ich hoffe, das Stahlwerk hier nebenan im Duisburger Ruhrpott hat dadurch keine Explosionen oder ähnliches.

Wolfi Gassler (01:00:05 - 01:00:51) Teilen

Und sonst, wenn Leute jetzt eingeschlafen sind, auch kein Problem, weil ihr habt mittlerweile herausbekommen, dass es ganz viele Einschlaf-Podcasts gibt und die wirklich boomen. Insofern, wenn wir da eine gewisse Hörerschaft covern können, auch kein Problem. Bin ich offen für alles. Und sonst, wenn ihr irgendwelche Fehler gefunden habt, was ja fast bei so einem Thema immer der Fall ist, bitte schaut vorbei in unserer Community oder wenn ihr irgendwelche anderen Rückmeldungen habt, Erfahrungen, Ideen zu dem ganzen Zahlenkomplex. Lasst uns das wissen, lasst es die anderen Community-Mitglieder wissen. Wir haben da immer rege Diskussionen und freuen uns natürlich auch darüber, noch ein bisschen weiter zu diskutieren. Und wer in der Community vorbeischaut und Andi auf einen Fehler darauf hinweist, den er in der Episode gemacht hat, der bekommt von mir ein Bier.

Andy Grunwald (01:00:51 - 01:00:52) Teilen

Gilt das für mich auch?

Wolfi Gassler (01:00:52 - 01:00:55) Teilen

Ja, aber nur wenn du Fehler bei mir findest, nicht eigene Fehler.

Andy Grunwald (01:00:55 - 01:01:02) Teilen

Okay. hätten wir das auch geklärt. Wir wünschen euch viel Spaß beim Programmieren und wenig Bugs. Bis zum nächsten Mal. Tschüss. Ciao.