Ich erzaehle seit einiger Zeit bei allen moeglichen Gelegenheiten, dass meiner Meinung nach Scriptsprachen in Zukunft auf die verwendung von Integer typen verzichten sollten und statt dessen double precission floats als basis number-type verwenden sollten, oder zumindest bei divisionen automatisch nach double float casten sollten. Offensichtlich kann double float mit der 56 bit Mantisse ein 32 bit vollstaendig abbilden. D.h. es kaeme hier in keiner weise zu einem Verlust an genauigkeit. Das mehr an Speicherplatz verbrauch ist ebenfalls zu vernachlaessigen: das geht in aller Regel im Verwaltungsoverhead der VM unter.
Die Vorteile liegen auf der Hand: ersten muss man sich bei Sprachen mit dynamischer typisierung dann keine gedanken darueber machen, ob eine variable jetzt nun int oder float ist und wie eine divison nun definiert ist (das ist ein punkt der mich an python 2 aergert - afaik hat kommt bei python 3 bei einer division immer ein float raus, ausser man verwenden den speziellen // operator fuer integer divisionen) und andererseit macht es das VM design etwas einfacher wenn man es nur mit einem number-type zu tun hat.
Das Gegenargument bleibt immer die performance. Also hab ich mal einen kleinen Test mit zwei typischen integer algorithmen gemacht: Das zaehlen von primzahlen mit einem ganz trivialen primtest und einfach nur zaehlen ohne weitere berechnungen:
int testi(int n)
{
int counter = 0;
for (int i = 2; i < n; i++)
{
for (int j = 2; j < i; j++)
if (i % j == 0)
goto next_candidate;
counter++;
next_candidate:;
}
return counter;
}
int test2i(int a, int b)
{
int counter = 0;
for (int i = 0; i < a; i += b)
for (int j = 0; j < a; j += b)
counter++;
return counter;
}
diese funktionen hab ich drei mal implementiert: fuer die C-typen int, float und double. bei float und double wird die modulo division mit der math.h funktion fmodf() bzw. fmod() umgesetzt. die implentierungen hab ich in jeweils eigene c-file gelegt und nochmals ein extra c-file mit einer main() implentierung erstellt. durch die verwendung jeweils eigener c-dateien soll sichergestellt werden, dass der compiler die funktion moeglichst generisch uebersetzt und nicht mit inlining und const folding in die main implementierung hineinzieht. Compiliert habe ich das ganze mit gcc 4.3.1 (-O3 -march=i386) und getestet auf meinem AMD Athlon(tm) 64 X2 Dual Core Processor 6000+. Im Test wird die erste funktion jeweils mit dem parameter 100000 und die zweite jeweils mit den parametern 40000 und 1 gestartet.
Das Ergebnis des Primzahlen-Tests:
Die integer variante braucht ganze 6,614 Sekunden um durchzulaufen. Die float bzw. double variante braucht 4,171 bzw. 4,172 Sekunden, ist also sogar deutchlich schneller!
Das Ergebnis des Zaehlerschleifen-Tests:
Die integer variante braucht 1,666 Sekuden. Die float bzw. double variante braucht 2,486 bzw. 2,450 Sekunden. Hier hat die integer variante klar die nase vorn!
Fazit: Es liegen keine Welten zwischen integer und float performance. Gerade bei interpretierten Sprachen durfte sich der tatsaechliche Performanceunterschied kaum bemerkbar machen. Bei JIT compilation muesste man sich da schon mehr gedanken machen um die maximale performance rausholen zu koennen, und das erste beispiel zeigt, dass hier ein JIT compiler unter umstaenden sogar mehr performance rausholen koennte wenn integer typen (zumindest in bestimmten faellen) zu floats kompiliert werden. Der Python3 Ansatz den Divisionsoperator unabhaenig von den Operanden als floating point division zu implementieren und einen eigenen operator fuer integer divisionen einzufuehren erscheint mir aber in jedem falle sinnvoll. Die Bestrebungen in ECMA-Script 4 und Perl 6 eigene int typen einzufuehren halte ich dafuer fuer fragwuerdig, vor allem weil man davon ausgehen kann, dass bis zur umsetzung von ECMA-Script 4 und Perl 6 wahrscheinlich auch alle embedded CPUs, die maechtig genug zum hosten dieser Sprachen sind (ECMA-Script findet z.Bsp. bereits Anwendung bei den HD-DVD Menues als VM-Backend) ueber mindestens so schnelle floating point wie fixkomma einheiten verfuegen werden.