[linux-l] SQL
Volker Grabsch
vog at notjusthosting.com
Fr Okt 27 00:42:11 CEST 2006
On Thu, Oct 26, 2006 at 10:13:24AM +0200, Steffen Dettmer wrote:
> > (bevor die Gauß-Kenner jetzt kommen: Jaja, man addiert auch nicht alle
> > Zahlen zusammen, sondern kommt mit einer Inkrementierung, einer
> > Multiplikation und einer Halbierung aus. Aber habt ihr euch schonmal
> > gefragt, wie man letzteres tut, ohne dabei den Zahlenbereich dabei
> > zu sprengen?
>
> Halbierung ohne dabei den Zahlenbereich zu sprengen? Einmal binär
> nach rechts schieben...
[...]
> Ja, daher sollte man auch erst halbieren, aber da muss man wohl ne
> ungerade/gerade Fallunterscheidung machen (was binär bei unsigned ints
> wieder einfach ist).
100 Punkte für den Kandidaten. Ich hatte gehofft, auch ohne
Fallunterscheidung könnte man auskommen, wie in einer "geschlossenen
Formel" eben, also im Maschinencode ohne Jump/Call auskommen. Da
ist mir aber noch nichts eingefallen.
> Multiplikation geht natürlich so nicht, aber selbst echtes Adieren ist
> nicht sicher. Das oben (1mio) passt ja auch nicht in 32 Bit.
Es ging auch nur um den einen Grenzfall, wo die Multiplikation versagt,
aber die Addition nicht.
> > Dann wäre die Multiplikation ne Katastrophe, aber die Addierschleife
> > würde korrekt arbeiten.)
>
> So, jetzt mal noch was: gibt es deinen extrem konstruierten Grenzfall
> überhaupt? Also eine Reihe derartiger Zahlen, deren Summe 4.294.967.296
> ist? Wie ist die grösste (zum Nachrechnen für mich :))
>
> Halte ich für ziemlich unwahrscheinlich, dass es die gibt :-)
Wenn man Wahrscheinlichkeitsrechnung und Zahlentheorie mixt, muss man
sehr vorsichtig sein ...
Also, nehmen wir die größe 16-Bit-Zahl, also die Wurzel von unserer
Grenze:
n = 65536
Dann ist n-1 auf jeden Fall zu klein:
(n-1)*n < n^2 = 4294...
Und n liegt auf jeden Fall drüber:
n*(n+1) > n^2 = 4294...
Das heißt, unser konstruierter Grenzfall liegt *immer* bei der Wurzel.
Die Wurzel ist zu groß, die Wurzel-1 ist zu klein.
Jetzt ist also nur noch die Frage, ob die Wurzel, also n, nun als
Gegenbeispiel taugt oder nicht. Aber da unser n > 1 ist, folgt:
n*(n+1)/2 < n*(n+n)/2 = n^2 = 4294...
Oder mit unseren konkreten Zahlen zum Nachrechnen:
1+2+...+65536 = 2147516416, also noch 32 Bit
Die Multiplikation in der Gauß-Formeln hingegen liefert den
Zwischenwert:
65536*65537 = 4295032832, also sprengt die 32 Bit
Wie oben gezeigt funktioniert diese Konstruktion ganz allgemein.
Für eine 2k-Bit-Architektur liefert n = 2^k das Gegenbeispiel.
(Um n > 1 zu erfüllen, muss k > 0 gelten, aber wir betrachten
hier eh keine 0-Bit-Architekturen :-))
Zugegeben, die ungeraden k habe ich jetzt nicht untersucht.
Aber schon die geraden k beweisen, dass die "Chance" bei
mind. 50% liegt.
Für ungerade k will ich mir jetzt keinen Beweis aus den Fingern
saugen, das Runden wird ekelhaft. Aber im konkreten Fall einer
31-Bit-Architektur funktioniert n = 46341:
46341*46342 > 2^31
46341*46342/2 < 2^31
Das heißt, auch für vorzeichenbehaftete 32-Bit-Integers funktioniert
die Konstruktion.
Ein C-Programm, das diese Schwäche tatsächlich aufdeckt, wäre nicht
schlecht ... hat einer Lust?
Viele Grüße,
Volker
--
Volker Grabsch
---<<(())>>---
Administrator
NotJustHosting GbR
Mehr Informationen über die Mailingliste linux-l