Carry Bit: How does it work?

Deutsch

Most of us know from elementary school how to add multi-digit numbers on paper. Usage of the carry bit is the same concept, but not for base 10, not even for base 2, but for base 256 (in the old 8-bit-days), base 65536 (in the almost as old 16-bit-days), base 4294967296 (32 bit) or base 18446744073709551616 (64 bit), whatever is the word width of the CPU. Always using powers of two is common today, but it is quite possible that this will change from bits to trits (having three possible values, -1, 0 and 1) in the far future.

I do not think that application development should be dealing with low level stuff like bits and bytes, but currently common programming languages like Java, C, C++, C# and more would not let you get away with that, you have to be aware of the bits underlying their numeric types to some extent. So it is a good idea to spend some effort on understanding this. Unfortunately all of these languages are lacking the carry bit, but it is anyway useful to understand the concept.

I have been writing software since the beginning of the 80es. The computers available to me at that time where 8-bit with a 6502- or 6510-CPU and 1 MHz clock speed. Yes, it was 1 MHz, not 1 GHz. It was possible to program them in some BASIC-dialect, but that was quite useless for many purposes because it was simply too slow. Compiled languages existed, but were too clumsy and too big to be handled properly on those computers, at least the ones that I have seen. So assembly language was the way to go. In later years I have also learned to use the 680×0 assembly language and the 80×86 assembly language, but after the mid 90es that has not happened any more. An 8-bit CPU can add two 8-bit numbers and yield an 8-bit result. For this two variants need to be distinguished, namely signed and unsigned integers. For signed numbers it is common to use 2’s complement. That means that the highest bit encodes the sign. So all numbers from 0 to 127 are positive integers as expected. 127 has the 8-bit representation 01111111. Now it would be tempting to assume that 10000000 stands for the next number, which would be +128, but it does not. Having the highest bit 1 makes this a negative number, so this is -128. Those who are familiar with modular arithmetic should find this easily understandable, it is just a matter of choosing the representatives for the residue classes. But this should not disturb you, if you have no recent experience with modular arithmetic, just accept the fact that 10000000 stands for -128. Further increments of this number make it less negative, so 10000001 stands for -127 and 11111111 for -1. For unsigned numbers, the 8 bits are used to express any number from 0 to 255.

For introducing the carry bit let us start with unsigned integral numbers. The possible values of a word are 0 to 2^n-1 where n is the word width in bits, which would be 8 in our example. Current CPUs have off course 64-bit word width, but that does not change the principle, so we stick with 8-bit to make it more readable. Just use your imagination for getting this to 32, 64, 96 or 128 bits.

So now the bit sequence 11111111 stands for 255. Using an assembly language command that is often called ADD or something similar, it is possible to add two such numbers. This addition can typically be performed by the CPU within one or two clock cycles. The sum of two 8-bit numbers is in the range from 0 through 510 (111111110 in binary), which is a little bit too much for one byte. One bit more would be sufficient to express this result. The workaround is to accept the lower 8 bits as the result, but to retain the upper ninth bit, which can be 0 or 1, in the so called carry bit or carry flag. It is possible to query it and use a different program flow depending on it, for example for handling overflows, in case successive operation cannot handle more than 8 bit. But there is also an elegant solution for adding numbers that are several bytes (or several machine words) long. From the second addition onwards a so called ADC („add with carry“) is used. The carry bit is included as third summand. This can create results from 0 to 511 (111111111 in binary). Again we are getting a carry bit. This can be continued until all bytes from both summands have been processed, just using 0 if one summand is shorter than the other one. If the carry bit is not 0, one more addition with both summand 0 and the carry bit has to be performed, yielding a result that is longer than the longer summand. This can off course also be achieved by just assuming 1, but this is really an implementation detail.

So it is possible to write a simple long integer addition in assembly language. One of the most painful design mistakes of current programming languages, especially of C is not providing convenient facilities to access the carry bit, so a lot of weird coding is used to work around this when writing a long integer arithmetic. Usually 64-bit arithemetic is used to do 32-bit calculations and the upper 32 bits are used for the carry bit. Actually, it is not that hard to recover the carry bit, but it is anyway a bit annoying.

Subtraction of long integers can be done in a quite similar way, using something like SBC („subtract with carry“) or SBB („subtract with borrow“), depending on how the carry bit is interpreted when subtracting.

For signed integer special care has to be taken for the highest bit of the highest word of each summand, which is the sign. Often a so called overflow but comes in handy, which allows to recognize if an additional machine word is needed for the result.

Within the CPU of current 64 bit hardware it could theoretically be possible to do the 64-bit addition internally bit-wise or byte-wise one step after the other. I do not really know the implementation details of ARM, Intel and AMD, but I assume that much more parallelism is used for performing such operation within one CPU cycle for all 64 bits. It is possible to use algorithms for long integer addition that make use of parallel computations and that can run much faster than what has been described here. They work for the bits and bytes within the CPU, but they can also be used for very long numbers when having a large number of CPUs, most typically in a SIMD fashion that is available on graphics devices misused for doing calculations. I might be willing to write about this, if interest is indicated by readers.

It is quite interesting to look how multiplication, division, square roots, cube roots and more are calculated (or approximated). I have a lot of experience with that so it would be possible to write about hat. In short these operations can be done quite easily on modern CPUs, because they have already quite sophisticated multiplication and division functions in the assembly language level, but I have off course been able to write such operations even for 8-bit CPUs lacking multiplication and division commands. Even that I could cover, but that would be more for nostalgic reasons. Again there are much better algorithms than the naïve ones for multiplication of very long integers.

Links

Share Button

Kein kommerzieller Support mehr für Glassfish

Oracle stellt den kommerziellen Support für Glassfish ein und empfiehlt Kunden, die an solchem Support interessiert sind, auf WebLogic umzustellen:

Oracle stellt kommerziellen Support für GlassFish ein.

Die Frage ist natürlich, ob man dann nicht ein paar andere Umstellungen überdenkt:

  • Wenn es EJB sein muss, ist vielleicht auch der WildFly-Applikationsserver von JBoss eine Option
  • Wenn es Java sein muss, ist vielleicht auch Spring eine Alternative
  • Wenn es die JVM sein muss, sind Scala, Clojure oder JRuby einige weitere Möglichkeiten. Diese bringen in der Regel ihre eigenen Frameworks mit. Wer möchte noch EJB benutzen, wenn er schon bei JRuby, Scala oder Clojure angelangt ist? Ja, theoretisch ginge das wohl, EJBs in diesen Sprachen zu entwickeln.
  • Wenn nicht es nicht einmal die JVM sein muss, gibt es viele Möglichkeiten, die ich der Phantasie des Lesers überlasse.

Kurz gesagt, ich will hier nicht den Ruhm von EJB schmälern. Das tue ich vielleicht einmal in anderen Blog-Beiträgen. Aber niemand muss von Glassfish auf WebLogic umstellen. Und schon gar nicht muss man sich bei dem prall gefüllten Satz an Alternativen von Oracle bei den Verhandlungen über den Tisch ziehen lassen.

Nur benötigen diese Umstellungen immer viel Zeit und Geld und sie müssen gut geplant werden. Deshalb ist es sicher gut, längerfristig die Alternativen vorzubereiten und nicht erst wenn es schon zu spät ist. Sonst geht mit einem virtuellen Schild um den Hals in die Verhandlungen mit Oracle, auf dem steht, dass man gerne über den Tisch gezogen werden möchte.

Es sei dem Leser überlassen, seine Schlussfolgerungen für andere technisch interessante Softwareprodukte aus demselben Haus zu ziehen, z.B. mySQL oder Solaris. Und ja, man könnte theoretisch für diese Produkte ähnliche Listen anfertigen.

Share Button

Multidispatch (Multimethoden): verpassen wir etwas

Objektorientierte Programmiersprachen werden nach meiner Meinung eigentlich erst wirklich objektorientiert, wenn sie Polymorphie unterstützen. Das bedeutet, dass ein Stück Progammcode mit einem Objekt gewisse Manipulationen durchführt und dabei Methoden des Objekts aufruft. Diese tun etwas verschiedenes, je nach dem welches Objekt hier angesprochen wird, denn es ist eine Eigenschaft des Objekts, welche Methode wirklich aufgerufen wird. In vielen Objektorientierten Programmiersprachen, wie zum Beispiel Java oder C# oder C++ ist das so gelöst, dass das Objekt einer Klasse angehört und die Klasse die Methodenimplementierung enthält, aber es können natürlich auch Methoden direkt an einzelnen Objekten aufgehängt sein. Für die Freunde von C# und C++ sei daran erinnert, dass „virtual“ hier nicht fehlen darf.

Das ist alles wunderbar und man kann damit sehr viel anfangen. Nun wird die heile Welt gestört, wenn man sich irgendwelche Konzepte aus nie wirklich Mainstream gewordenen Programmiersprachen wie Common Lisp mit CLOS anschaut, wo es sogenanntes Multidispatch gibt. Die aufgerufene Methode hängt also nicht nur vom ersten speziellen Parameter, also dem Objekt, das oft vor dem „.“ steht, ab, sondern von allen Parametern. Das macht es unübersichtlich und niemand braucht so etwas, könnte man meinen. Das mag ja alles stimmen, aber wir werden doch mit Situationen konfrontiert, wo das Thema sehr relevant wird.

Nehmen wir an, man führt einen neuen numerischen Typ ein, z.B. Rational für rationale Zahlen \Bbb Q=\{ \frac{a}{b} : a, b \in \Bbb Z \wedge b > 0 \}. Nun braucht man Methoden für die Grundrechenarten, was sehr schön funktioniert, wenn man z.B. zwei rationale Zahlen addieren will. Nun soll es aber auch funktionieren, eine ganze Zahl zu einer rationalen Zahl zu addieren. Dafür kann man die „+“-Methode oder weniger schön die „add“-Methode noch einmal mehr überladen und einen ganzzahligen Parameter verstehen oder innerhalb der Methode diesen Fall zur Laufzeit erkennen. Der erste Ansatz greift leider zu kurz, weil wegen Vererbungshierarchie und gerade wegen der Polymorphie der genaue Type zur Compilezeit nicht bekannt ist und daher auf die allgemeine Methode, etwa so etwas wie

+(x : Numeric) ,

zurückgefallen wird, die wiederum abhängig vom realen Typ von x auf die richtige Methode oder den richtigen Methodenteil führen sollte.
Das ist alles noch gut machbar, man darf es nur nicht vergessen.

Aber was passiert nun, wenn q rational und n ganzzahlig ist und wir nicht q+n, sondern n+q schreiben? Nun müsste man Integer (oder BigInteger) oder was auch immer der Typ ist, hoffentlich ohne diesen absurden Überlauf bei 2^{31}-1 wie die java-ints, nachträglich beibrigen, rational zu verstehen. In Ruby kann man zumindest noch nachträglich die Methode + von Integer ändern und durch eine eigene ersetzen, die auch Rational versteht, aber der Ansatz stößt irgendwann an Grenzen. In Ruby behilft man sich oft damit, dass die +-Methode der linken Seite eine „coerce“-Methode der rechten Seite mit der linken Seite als Parameter aufruft, um Konvertierungen zu machen. Damit kommt man recht weit, aber man muss sehr genau hinschauen, was man tut.

Nun kommt sicher der Einwand, dass Operatorüberladen sowieso „böse“ ist. Das hilft aber hier nichts, die Probleme treten in identischer Form auf, wenn man es „add“ statt „+“ nennt.

Der zweite Einwand ist vielleicht, dass man nicht jeden Tag neue numerische Typen schreibt. Aber man schreibt doch hoffentlich ab und zu neue Klassen und nutzt Vererbung. Da muss man dann eine equals-Methode oder so etwas ähnliches implementieren. Und schon ist das Problem sehr relevant. In der Regel habe ich das dadurch gelöst, dass equals zuerst die Klassen von linker Seite (self oder this) und rechter Seite vergleicht und nur wenn die gleich sind, überhaupt weiter vergleicht. Das ist meistens ein guter Ansatz. Aber manchmal muss man wirklich Gleichheit zwischen Objekten zulassen, die nicht derselben Klasse angehören. Dann ist es schon eine Herausforderung, das korrekt und halbwegs solide zu lösen. Man sieht also, dass wir hier wirklich etwas verpassen… Aber solange man die Konzepte kennt, kann man sie grundsätzlich in jeder Programmiersprache anwenden, der Aufwand ist nur etwas größer.

Java ist hier tatsächlich etwas schlechter gestellt als z.B. Scala oder Ruby, weil man sehr schlechte Möglichkeiten hat, die eingebaute equals-Methode zu ersetzen. Während es bei SortedSet die Wahlmöglichkeit gibt, Comparable oder einen Comparator zu verwenden, setzen HashSet und HashMap fast immer auf die interne hashCode() und equals()-Methode und man muss sich mit Wrappern oder geeigneten inneren Klassen behelfen, um eine zweites Interface für dasselbe Objekt mit anderen equals()- und hashCode()-Methoden zu liefern.

Share Button

Scala Exchange 2013

Deutsch

I have visited the conference ScalaX 2013 in London on the beginning of December.

It was really fun. The talks were quite challenging, maybe even a little bit more than on other conferences I have visited, but that was really fun to listen to. About 400 participants were there and three tracks were available. So it was possible to learn a lot about advanced concepts in functional programming and software architecture with a focus on Scala, but also some Haskell and Clojure.

Some interesting talks were:

Share Button

Besuch bei Scala Exchange 2013

English

Gleich ein paar Wochen nach der Devoxx habe ich noch so eine Konferenz besucht, diesmal nur zwei Tage und unter dem Namen „Scala Exchange“ oder kurz #scalaX.
Es ging hauptsächlich um funktionale Programmierung und Architektur und das wiederum meistens recht „Scala-lastig“.
Die Vorträge waren um einiges anspruchsvoller als bei der Devoxx, aber das machte vielleicht auch den speziellen Reiz aus.

Interessante Vorträge waren unter anderem:

Share Button

Devoxx 2013 Part 2

During the time from 2013-11-13 to 2013-11-15 I have been attending the Devoxx-conference in Antwerp in Belgium.
Most of the speeches I have been listening too were just great, like for example:

Share Button

Devoxx 2013 Teil 2

In der Zeit vom 13. bis zum 15. November habe ich die Devoxx-Konferenz in Antwerpen besucht.
Die meisten Vorträge waren wieder sehr gut, z.B.:

Hier ist noch ein guter Blogbeitrag zur Devoxx 2013.

Share Button

UTF-16 bei Zeichenketten in Java

English

Zeichenketten in Java und in vielen JVM-Sprachen enthalten Unicode-Zeichen und sind mit utf-16 codiert. Es war sehr weitsichtig, schon in den 90er-Jahren an Unicode zu denken und das als alleinige Möglichkeit vorzusehen. Man hat sich so erspart, das Durcheinander zu haben, welche Zeichenkette jetzt in welcher Codierung vorliegt, weil alle gleich sind, und auch zumindest für gängige europäische und westasiatische Sprachen die Handhabung vereinfacht, weil da ein Zeichen zwei Bytes sind. Der Nachteil mit dem etwas größeren Speicherverbrauch spielt fast keine Rolle, weil man mit ein paar Zeichenketten sehr selten an die Grenzen stößt. Mit 64-Bit-CPUs (und 64-Bit-JVM) kann man ja fast beliebig viel Hauptspeicher einsetzen.

Aber es gibt auch Applikationen, die trotzdem mit ihrem Speicherverbrauch an Grenzen stoßen. So könnte man auf die Idee kommen, eigene Zeichenketten zu verwenden, die utf-8 statt utf-16 verwenden. Die entsprechende Konvertierung ist nicht schwierig und sicher im Netz zu finden, sogar in der eigenen Java-Libary. Leider sind die Zeichenketten aber an so vielen Stellen vorgesehen und man kann sie nicht einfach durch eine andere Klasse ersetzen. Was bleibt sind also lästige explizite Konvertierungen. Aber allein mit diesem Ansatz kann man natürlich eine Menge Speicher sparen.

Eine andere Idee wäre es, Zeichenketten zu komprimieren. Wenn sie lang genug sind, funktionieren Algorithmen wie gzip auf einer einzelnen Zeichenkette. Das erschwert natürlich den selektiven Zugriff auf einzelne Teile der Zeichenkette, aber das Problem hat man schon mit utf-8, wo man nicht genau weiß, ab welchem Byte nun das n-te Zeichen beginnt, ohne sie von Anfang an durchzugehen. Aber wir müssen auch damit rechnen, dass es nicht einzelne lange Zeichenketten gibt, sondern sehr viele, die jeweils zu kurz sind, um für sich genommen mit einer Kompression kleiner zu werden. Wenn man nun aber die Gesamtheit der Zeichenketten ungefähr kennt, kann man eine Komprimierung generieren, die für diesen Satz von Zeichenketten gute Ergebnisse bringt. Das bedeutet, dass man ähnlich wie bei der Umstellung von utf-16 auf utf-8 einzelne Byte-Sequenzen der unkomprimierten Zeichenkette durch anderen Byte-Sequenzen für die komprimierte Zeichenkette ersetzt. Die häufig vorkommenden Sequenzen werden durch kürzere ersetzt, die selteneren durch längere. So kann man mit weniger Bytes auskommen. Die Regel, wie das Komprimieren und Dekomprimieren funktioniert, muss man nur einmal für das ganze Programm speichern und nicht wie bei der ersten Idee für den Einsatz von gzip in jeder Zeichenkette einzeln.

Es empfiehlt sich unbedingt, die folgenden Punkte zu beachten:

  1. Sind wirklich die Zeichenketten ein Problem mit ihrem Speicherverbrauch?
  2. Lässt sich dieses durch andere, einfachere Optimierungen der Software lösen?
  3. Lasst es sich durch Hardware lösen?
  4. Gibt es schon geeignete oder adaptierbare Lösungen im Netz? Oder in der eigenen Organisation?
  5. Eine neue String-Klasse ist so grundlegend, dass man sie unbedingt gut testen muss. Unit-Tests sollten wirklich ausführlich sein.
Share Button

Devoxx 2013 Teil 1

Ich besuche in dieser Woche die Devoxx-Konferenz in Antwerpen. Es gibt wieder viele interessante und auch unterhaltsame Vorträge über Software-Architektur, Entwicklungsprozesse, Security, Team-Organisation und neue Technologien. Dart 1.0 als möglicher Ersatz für Javascript ist zum Beispiel vorgestellt worden. Es ist immer gut, wenn man noch etwas dazu lernen kann, denn Leute, die schon alles wissen, bremsen früher oder später ihre Teams oder ihre Projekte aus, weil alles Neue abgelehnt wird…

Ich hoffe, dass ich nächstes Jahr wieder dort sein kann.

Mehr Details dazu kommen später.

Voriges Jahr war ich auch dort.

Share Button

Devoxx 2013 part 1

2013 I am visiting Devoxx in Antwerp again. It is quite interesting, because they have invited good speakers who know their stuff and are fun to listen to.

So I am learning a lot about software architecture, software development, team organization, security and new technologies. It is always good not to know everything and to be able to learn new stuff, because people who know everything already usually slow down their projects sooner or later. So I hope to be there again next year. 😉

I will write more in another post …

Btw. last year was great as well. 😉

Share Button