Forum: Mikrocontroller und Digitale Elektronik Überlauf bei Multiplikation verhindern


von Walter T. (nicolas)


Lesenswert?

Guten Morgen,

ich habe zwei Variablen int64_t a, b, bei denen ich wissen will, ob das 
Produkt in eine 64-Bit-Variable passt.

Gibt es einen einfacheren Weg, als bei beiden die führenden Nullen zu 
zählen und zu schauen, ob die Summe mindestens 63 ergibt?

Viele Grüße
W.T.

von Wolfgang (Gast)


Lesenswert?

Walter T. schrieb:
> Gibt es einen einfacheren Weg, als bei beiden die führenden Nullen zu
> zählen und zu schauen, ob die Summe mindestens 63 ergibt?

Werte einfach die Bitpositionen der jeweils ersten Eins aus. Damit liest 
du auf der sicheren Seite.

von (prx) A. K. (prx)


Lesenswert?

Walter T. schrieb:
> Gibt es einen einfacheren Weg, als bei beiden die führenden Nullen zu
> zählen und zu schauen, ob die Summe mindestens 63 ergibt?

Zu 128 Bits multiplizieren und prüfen ob es passt. Je nach Prozessor und 
Sprache kann das sowohl einfacher als auch schneller sein. ;-)

von Possetitjel (Gast)


Lesenswert?

A. K. schrieb:

> Walter T. schrieb:
>> Gibt es einen einfacheren Weg, als bei beiden die
>> führenden Nullen zu zählen und zu schauen, ob die
>> Summe mindestens 63 ergibt?
>
> Zu 128 Bits multiplizieren und prüfen ob es passt.
> Je nach Prozessor und Sprache kann das sowohl einfacher
> als auch schneller sein. ;-)

Naja, es wäre einen Versuch wert, ob man das -- je nach
Prozessor und Sprache -- etwas beschleunigen kann, wenn
man die Multiplikation 64x64-->128 von Hand macht.

Ich würde von der binomischen Formel ausgehen.

Zunächst kann man sich überlegen, dass wenigstens EINE
der beiden Zahlen kleiner als 2^32 sein muss. Wenn das
nicht der Fall ist, kann man abbrechen.

Weiterhin springt ins Auge, dass das Produkt der (unteren
32 Bit der) kleineren Zahl mit den oberen 32 Bit der
größeren ebenfalls kleiner als 2^32 sein muss. Man rechnet
das also aus und bricht ab, wenn es nicht passt.

Jetzt ist nur noch zu prüfen, ob die Summe aus dem bisherigen
Zwischenergebnis und dem Produkt der beiden unteren 32 Bit
keinen Überlauf gibt. Fertig.

von (prx) A. K. (prx)


Lesenswert?

Possetitjel schrieb:
> etwas beschleunigen kann, wenn
> man die Multiplikation 64x64-->128 von Hand macht.

In C ist das einzige Problem, eine vorhandene 64x64 zu 128 
Multiplikation hinzuschreiben. Wenns kein Intrinsic gibt, ist ASM nötig.

AMD Ryzen:
 MUL 64x64 zu 128 braucht 3 Takte
 2xBSR + 1xADD braucht 9 Takte
Intel Skylake:
 MUL 64x64 zu 128 braucht 3 Takte
 2xBSR + 1xADD braucht 3 Takte

Sieht natürlich etwas anders aus, wenn die Hardware das nicht hergibt.

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

A. K. schrieb:

> Sieht natürlich etwas anders aus, wenn die Hardware
> das nicht hergibt.

Davon (dass die Hardware das nicht hergibt) bin ich
ausgegangen. Walter ist mir bisher nicht als jemand
aufgefallen, der exzessiv Zeit in unsinnige Mikro-
Optimierung steckt. :)

Andernfalls hast Du natürlich Recht.

von (prx) A. K. (prx)


Lesenswert?

Possetitjel schrieb:
> Zunächst kann man sich überlegen, dass wenigstens EINE
> der beiden Zahlen kleiner als 2^32 sein muss. Wenn das
> nicht der Fall ist, kann man abbrechen.

Wenn auch nur eine der oberen Hälften nicht 0 ist und beiden Seiten 
nicht 0 sind hat man bereits verloren.

: Bearbeitet durch User
von Nils P. (torus)


Lesenswert?

A. K. schrieb:
> AMD Ryzen:
>  MUL 64x64 zu 128 braucht 3 Takte
>  2xBSR + 1xADD braucht 9 Takte
> Intel Skylake:
>  MUL 64x64 zu 128 braucht 3 Takte
>  2xBSR + 1xADD braucht 3 Takte

Warum nicht einfach nach der Multiplikation mit SETO oder JO direkt auf 
den Overflow reagieren?

von A. S. (Gast)


Lesenswert?

Negative Werte haben keine führenden Nullen.

Wenn unsigned, dann einfach prüfen ob das Ergebnis >= beide 
Eingangswerte ist.

Mit signed kommen ein paar Falluntersuchungen hinzu.

von (prx) A. K. (prx)


Lesenswert?

Nils P. schrieb:
> Warum nicht einfach nach der Multiplikation mit SETO oder JO direkt auf
> den Overflow reagieren?

Oder so.

von (prx) A. K. (prx)


Lesenswert?

Achim S. schrieb:
> Negative Werte haben keine führenden Nullen.

Da W.T. aber selbst vorschlägt, führende Nullen zu zählen, meint er eine 
vorzeichenlose Multiplikation.

Beitrag #5268020 wurde vom Autor gelöscht.
von (prx) A. K. (prx)


Lesenswert?

Possetitjel schrieb:
> Davon (dass die Hardware das nicht hergibt) bin ich
> ausgegangen.

Ich im Grunde auch. Meine erste Antwort war ursprünglich eher als 
Hinweis gedacht, dass in der Frage essentielle Information fehlt.

> Walter ist mir bisher nicht als jemand
> aufgefallen, der exzessiv Zeit in unsinnige Mikro-
> Optimierung steckt. :)

Nicht jeder kann sich ausmalen, dass eine solche riesige Multiplikation 
billiger sein kann als weit einfacher erscheindende Operationen. In 
Chipfläche ist sie es auch nicht.

Der schnellste Weg, in den 16-Bit Kisten von Microchip ein 32-Bit 
Registerpaar zu nullen, ist die Multiplikation mit 0. Weshalb der 
Compiler das auch genau so macht. Wer das nicht gesehen hat kommt von 
selber nicht unbedingt auf solche bizarr anmutenden Ideen.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Ehrlich gesagt geht es mir gar nicht um den schnellsten Weg. Das Ganze 
kommt in eine Initialisierungsroutine, die nur einmal aufgerufen wird. 
Eher: Das fühlt sich nach einem Standardproblem an - also könnte es eine 
Standardlösung™ geben. Und nicht selten hat die Standardlösung™ Vorteile 
gegenüber dem, was ich mir ausdenke (siehe auch z.B. A.K.s Beispiel zu 
32-Bit-Registern im PIC).

---

Possetitjel schrieb:
> Naja, es wäre einen Versuch wert, ob man das -- je nach
> Prozessor und Sprache -- etwas beschleunigen kann, wenn
> man die Multiplikation 64x64-->128 von Hand macht.

Ziel ist eine Multiplikation 64x64 -> 64, deswegen ja die Prüfung, ob 
das passt.

A. K. schrieb:
> Sieht natürlich etwas anders aus, wenn die Hardware das nicht hergibt.

Stimmt, ich habe nicht daran gedacht, daß auch in der Rubrik "µC und 
Digitale Elektronik" nicht unbedingt ein 64-Bit-Prozessor auszuschließen 
ist.

Zielplattform ist ARM Cortex M3, programmiert wird in C.

Achim S. schrieb:
> Negative Werte haben keine führenden Nullen.

Stimmt. Habe ich vergessen. Ist in meinem Fall nicht schlimm, weil die 
Werte auf jeden Fall positiv sind (per assert() sichergestellt), aber 
ich sollte es nicht vergessen, falls ich es mal auf ein anderes Problem 
anwenden will. (Für Vergleichstests mit der Lösung unten ist jetzt ein 
Test aauf INT_MIN und eine Betragsbildung drin).


---

Possetitjel schrieb:
> Ich würde von der binomischen Formel ausgehen.
>
> Zunächst kann man sich überlegen, [...]
>
> Weiterhin springt ins Auge, dass das Produkt der (unteren
> 32 Bit der) [...]
>
> Jetzt ist nur noch zu prüfen, [...]

Ob das wirklich schneller ist, als Nullen zu zählen, hängt vermutlich 
vor allem von den Zahlen selbst ab. Schön daran ist natürlich, das es 
direkt mit den Vorzeichen paßt. Ich denke, hier hilft nur ausprobieren 
und messen.

Beim Zählen sind weniger Fallunterscheidungen, die binomische Formel 
bedarf weniger Kommentare und benötigt keine Intrinsics. Beim Test mit 
Pseudozufallszahlen liefern aber beide das gleiche Ergebnis.

Danke für die Diskussion!

: Bearbeitet durch User
von Possetitjel (Gast)


Lesenswert?

A. K. schrieb:

> Possetitjel schrieb:
>> Zunächst kann man sich überlegen, dass wenigstens EINE
>> der beiden Zahlen kleiner als 2^32 sein muss. Wenn das
>> nicht der Fall ist, kann man abbrechen.
>
> Wenn auch nur eine der oberen Hälften nicht 0 ist und
> beiden Seiten nicht 0 sind hat man bereits verloren.

Nee: 2^48 * 4 = 2^50

Das ist ja genau das Problem, dessentwegen Walter die
Nullen zählen will.

von Dumdi D. (dumdidum)


Lesenswert?

Falls Du sowieso irgendwo im Progrann Fliesskommazahlen, koenntest Du 
auch auf float casten und schaun ob das Produkt in 64bit hereinpasst, 
dann die.Rechnung mit int durchfuehreb. (Ok, irgendwie wird mir jetzt 
auch uebel)

von Carl D. (jcw2)


Lesenswert?

Der M3 kann führende Nullen zählen:
CLZ Rd, Rm
Vorher von beiden Zahlen den Absolutwert ermittel (Vozeichen 
wegstreichen),
wenn die Summe der führenden Nullen beider Zahlen >= 64 ist, dann passt 
das Multiplikationsergebnis in 64Bit.

BTW, kann es sein, daß das was du vor hast, auch der 64Bit Compiler-Host 
machen könnte? -> constexpr

von (prx) A. K. (prx)


Lesenswert?

Possetitjel schrieb:
>> Wenn auch nur eine der oberen Hälften nicht 0 ist und
>> beiden Seiten nicht 0 sind hat man bereits verloren.
>
> Nee: 2^48 * 4 = 2^50

Und wo ist da nun das Problem?

Was ich nannte war eine notwendige Bedingung, nicht aber eine 
hinreichende. So hatte ich es deshalb auch formuliert.

von Possetitjel (Gast)


Lesenswert?

Walter T. schrieb:

> Possetitjel schrieb:
>> Ich würde von der binomischen Formel ausgehen.
>>
>> Zunächst kann man sich überlegen, [...]
>>
>> Weiterhin springt ins Auge, dass das Produkt der (unteren
>> 32 Bit der) [...]
>>
>> Jetzt ist nur noch zu prüfen, [...]
>
> Ob das wirklich schneller ist, als Nullen zu zählen, hängt
> vermutlich vor allem von den Zahlen selbst ab.

Hmm. Ich glaube, wir reden aneinander vorbei.

Wenn es direkt einen Maschinenbefehl für 64x64->128 gibt, ist
die Diskussion sinnlos, weil dann A.K.s Idee die Beste ist.

Wenn es direkt einen Maschinenbefehl für das Zählen führender
Nullen gibt, ist die Diskussion auch sinnlos, weil dann
(vermutlich) Dein ursprünglicher Vorschlag der Beste ist.

Wenn man aber nur eine Multiplikation 32x32->64 zur Verfügung
hat, muss man die Multiplikation 64x64-->??? in jedem Falle
nach der binomischen Formel zusammenbauen.

Der Unterschied zwischen der compilergenerierten und meiner
handgebastelten Variante liegt nur darin: Der Compiler rechnet
IMMER bis zum bitteren Ende, auch wenn das Resultat sowieso
zu groß wird. In meinem Vorschlag testet man nach jeder
Teilrechnung auf Überschreitung und bricht ggf. ab. Wenn man
bis zum Ende durchkommt, weiss man nicht nur, dass es passt,
sondern HAT BEREITS DAS ERGEBNIS.

von (prx) A. K. (prx)


Lesenswert?

A. K. schrieb:
>> Nee: 2^48 * 4 = 2^50
>
> Und wo ist da nun das Problem?

Sorry, Irrtum. Hatte was anderes im Kopf.

von Possetitjel (Gast)


Lesenswert?

A. K. schrieb:

> Possetitjel schrieb:
>>> Wenn auch nur eine der oberen Hälften nicht 0 ist und
>>> beiden Seiten nicht 0 sind hat man bereits verloren.
>>
>> Nee: 2^48 * 4 = 2^50
>
> Und wo ist da nun das Problem?
>
> Was ich nannte war eine notwendige Bedingung, nicht aber
> eine hinreichende. So hatte ich es deshalb auch formuliert.

Dann verstehe ich nicht, was Du mir sagen wolltest.

Beim Beispiel 2^48 * 4 ist die eine Zahl mit 32bit darstellbar,
die andere nicht; das Ergebnis passt aber in 64 Bit.

Im Beispiel 2^48 * 2^20 ist EBENFALLS die eine Zahl mit 32bit
darstellbar, die andere nicht -- das Ergebnis passt aber NICHT
in 64 Bit.

Man kann also nur ableiten: Wenn BEIDE 64bit-Zahlen nicht mit
32 Bit darstellbar sind, passt das Ergebnis GARANTIERT NICHT.
Wenn aber nur eine Zahl nicht mit 32 Bit darstellbar ist, weiss
man gar nichts.
Deswegen lautet mein Vorschlag: Auf Verdacht weiterrechnen und
nach dem nächsten Rechenschritt wieder prüfen.

von Possetitjel (Gast)


Lesenswert?

A. K. schrieb:
> A. K. schrieb:
>>> Nee: 2^48 * 4 = 2^50
>>
>> Und wo ist da nun das Problem?
>
> Sorry, Irrtum. Hatte was anderes im Kopf.

Ah. Okay. Zu spät gesehen.

von Possetitjel (Gast)


Lesenswert?

Carl D. schrieb:

> Der M3 kann führende Nullen zählen:

Dann ist mein Vorschlag natürlich gegenstandslos.

von (prx) A. K. (prx)


Lesenswert?

Possetitjel schrieb:
> Wenn es direkt einen Maschinenbefehl für das Zählen führender
> Nullen gibt, ist die Diskussion auch sinnlos, weil dann
> (vermutlich) Dein ursprünglicher Vorschlag der Beste ist.

Aber genau hinsehen. Die Bitzählerei kann billig sein. Oder ziemlich 
teuer, selbst wenn als Befehl vorhanden.

> Wenn man aber nur eine Multiplikation 32x32->64 zur Verfügung
> hat, muss man die Multiplikation 64x64-->??? in jedem Falle
> nach der binomischen Formel zusammenbauen.

Wobei auch hier die Laufzeit einzelner Operationen wichtig ist. Diese 
Strategie kann sich über die konkreten Prozessoren und Jahre ändern. Bei 
70 Takten für die einzelne Multiplikation lohnt sich dein 0-Test, bei 2 
Takten nicht.

> Der Unterschied zwischen der compilergenerierten und meiner
> handgebastelten Variante liegt nur darin: Der Compiler rechnet
> IMMER bis zum bitteren Ende, auch wenn das Resultat sowieso
> zu groß wird.

Was genau meinst du? Ein C Compiler bietet oft keine 128-Bit 
Multiplikation und die oft verfügbare 64-Bit Multiplikation liefert nur 
den unteren Teil, mit oder ohne Überlauf (mit Vorzeichen u.U. sogar 
einfach nur Unsinn).

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Dabei wollte ich doch nur...



Eigentlich ging es nur um den berühmten "kleinen Eingriff" - und 
irgendwie hat sich das (mal wieder) so ausgeartet, dass es den 
kompletten Vormittag gedauert hat.

Hier die beiden Varianten:
1
/* Testen, ob Produkt zweier Variablen in 64 Bit passt */
2
bool productFits64BitClz(int64_t a, int64_t b)
3
{
4
    if( (a == 0) || (a == 1) || (b == 0) || (b == 1) )
5
    {
6
        // -1 passt nicht bei INT_MIN
7
        return true;
8
    }
9
    else if( (a == INT64_MIN) || (b == INT64_MIN) )
10
    {
11
        return false;
12
    }
13
14
15
    // Aufspalten in Betrag und Vorzeichen
16
    uint_fast8_t sign = SIGN(a) * SIGN(b);
17
    a = ABS(a);
18
    b = ABS(b);
19
20
21
    int lza = __builtin_clzll(a);
22
    int lzb = __builtin_clzll(b);
23
    int nba = __builtin_popcountll(a);
24
    int nbb = __builtin_popcountll(b);
25
26
    int cmp;
27
    if( nba == 1 || nbb == 1)
28
    {
29
        cmp = 63;
30
    }
31
    else
32
    {
33
        cmp = 64;
34
    }
35
36
    if( lza + lzb <= cmp)
37
    {
38
        return false;
39
    }
40
    else
41
    {
42
        return true;
43
    }
44
}
45
46
47
/* Testen, ob Produkt zweier Variablen in 64 Bit passt */
48
bool productFits64BitBinom(int64_t a, int64_t b)
49
{
50
    if( (a == 0) || (a == 1) || (b == 0) || (b == 1) )
51
    {
52
        // -1 passt nicht bei INT_MIN
53
        return true;
54
    }
55
    else if( (a == INT64_MIN) || (b == INT64_MIN) )
56
    {
57
        return false;
58
    }
59
60
    // Aufspalten in Betrag und Vorzeichen
61
    uint_fast8_t sign = SIGN(a) * SIGN(b);
62
    a = ABS(a);
63
    b = ABS(b);
64
65
    // Faktoren in 32-Bit-Teile aufspalten
66
    uint64_t a1 = a/(1LL<<32);
67
    uint64_t a2 = a%(1LL<<32);
68
    //assert( a == a1*(1LL<<32) + a2);
69
70
    uint64_t b1 = b/(1LL<<32);
71
    uint64_t b2 = b%(1LL<<32);
72
    //assert( b == b1*(1LL<<32) + b2);
73
74
    // Beide vorderen Bloecke > 0 -> passt nicht
75
    if( a1 && b1 )
76
    {
77
        return false;
78
    }
79
80
    //assert( (a1 * b2 == 0) || (a2 * b1 == 0) );
81
82
    uint64_t prodmsb32 = a1*b2 + a2*b1 + (a2*b2)>>32;
83
84
    if( (prodmsb32>>32) && sign != -1 )
85
    {
86
        return false;
87
    }
88
    else if( (prodmsb32>>31) )
89
    {
90
        return false;
91
    }
92
    else
93
    {
94
        return true;
95
    }
96
}



Der ARM-GCC macht aus dem __builtin_clzll im Assembler (mehrere) 
clz-Operationen, für __builtin_popcountll wird eine Library-Funktion 
aufgerufen.

Mit diesem Stückchen wird es noch etwas billiger:
1
    /* Testen, ob Integer-Variable Zweierpotenz ist */
2
    static_inline bool poweroftwo(int32_t x)
3
    {
4
        return x && ((x & (x - 1)) == 0);
5
    }
aber irgendwie sind alle Varianten komplizierter als gedacht.

: Bearbeitet durch User
von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Führende 0en zu zählen liefert kein scharfes Kriterium!

Beispiel:

2^64 + 1 = 274177 * 67280421310721

d.h. Multiplikation der beiden Faktoren auf der rechten Seite führt zu 
einem Überlauf.

Vermindert man nun einen der beiden Faktoren um 1, dann gibt es keinen 
Überlauf mehr, obwohl die Anzahl der führenden 0en gleich bleibt 
(tatsächlich bleibt alles bis auf ein Low-Bit gleich):

274177 * 67280421310720 = 0xFFFFFFFFFFFBD100 < 2^64

Die SUmme führender 0en ist also hinreichend für eine Überlauf-freie 
Multiplikation, aber nicht notwendig für nicht-Überlauf.

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Johann L. schrieb:
> Führende 0en zu zählen liefert kein scharfes Kriterium!

Auweia! Du hast Recht!

(Auweia deshalb, weil das beim Testen hätte auffallen müssen...)

von Walter T. (nicolas)


Lesenswert?

Jetzt sollte das aber kugelsicher sein (und kürzer als die anderen 
Varianten ist es auch noch, insbesondere kein branch im ASM-Code)
1
/* Testen, ob Produkt zweier Variablen in 64 Bit passt */
2
bool productFits64BitMult(int64_t ai, int64_t bi)
3
{
4
    // Multiplikationsergebnis bei vorzeichenloser Zahl ist identisch
5
    uint64_t a = (uint64_t) ai;
6
    uint64_t b = (uint64_t) bi;
7
8
    // Multiplikation ausfuehren, aber Ergebnis direkt wegwerfen
9
    uint64_t akku;
10
    uint32_t a0, a1, b0, b1;
11
    a0 = a & 0xFFFFFFFF; // LSW
12
    a1 = a >> 32; // MSW
13
    b0 = b & 0xFFFFFFFF; // LSW
14
    b1 = b >> 32; // MSW
15
16
    akku = (uint64_t) a0 * b0;
17
    akku >>=32; // Hintere 32 Stellen verwerfen
18
    akku += (uint64_t) a1 * b0 + (uint64_t) a0 * b1;
19
    akku >>=32; // Hintere 32 Stellen verwerfen
20
    akku += (uint64_t) a1 * b1;
21
22
    if( akku )
23
    {
24
        return false;
25
    }
26
    else
27
    {
28
        return true;
29
    }
30
}

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Walter T. schrieb:
>     akku += (uint64_t) a1 * b0 + (uint64_t) a0 * b1;

Hier kann es zu einem Überlauf kommen.

Manche Compiler unterstützten __int128 für bestimmte Targets, z.B. GCC 
für x86_64.  Damit geht's dann einfacher.

Ansonsten implementiert man eine 64×64=128 Multiplikation (was du ja 
versuchst) und testet den High-Teil.  Teilweise kann man Low-Teile 
Ignorieren bzw. daraus resultiernde Carry weil (-1u)*(-1u) genügend 
"Headroom" hat bis zum Überlauf.

Weiters gibt es compilerspezifische Built-ins, siehe etwa

http://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html

Allerdings verhindern die keinen Overflow (wie von dir gewünscht), 
sondern lassen ihn lediglich erkennen.  Einen Overflow verhindern geht 
nur mit einer 128-Bit ARithmetik bzw. einer Arithmetik, die den 
möglichen Wertebereich abbilden kann.

: Bearbeitet durch User
von Jacko (Gast)


Lesenswert?

Zum Programmstart zur Initialisierung???

Da kann der Compiler doch noch ausrechnen,
ob #VarA * #VarB < 2^64 ist...

ELSE geht das Prog eben nicht. Gähn...

von Possetitjel (Gast)


Lesenswert?

A. K. schrieb:

>> Wenn man aber nur eine Multiplikation 32x32->64 zur Verfügung
>> hat, muss man die Multiplikation 64x64-->??? in jedem Falle
>> nach der binomischen Formel zusammenbauen.
>
> Wobei auch hier die Laufzeit einzelner Operationen wichtig ist.
> Diese Strategie kann sich über die konkreten Prozessoren und
> Jahre ändern.

Ja, sicher.
Es geht mir gar nicht um eine konkrete Implementierung, die
den allerletzten Taktzyklus herausquetscht, sondern um eine
algorithmische Idee, die auf den meisten Plattformen "ziemlich
gut" ist.

Das Nullen-Zählen sieht erstmal einfach aus, kann aber (je
nach Befehlssatz des Prozessors) in echte Arbeit ausarten.

> Bei 70 Takten für die einzelne Multiplikation lohnt sich
> dein 0-Test, bei 2 Takten nicht.

Ich habe Deine Idee erst nach der 2. Wiederholung verstanden.

Eigentlich ist es am elegantesten, auch das oberste Teil-
produkt einfach auszurechnen und auf Null zu testen, weil
man dadurch die Fallunterscheidung vermeidet. Da hast Du
schon Recht. Der Preis wäre aber eine Multiplikation, die in
jedem Falle ausgeführt werden muss.
Bei Test&Sprung dagegen riskiert man auf schnellen Maschinen
Strafzyklen.

Ich würde schätzungsweise auf dem Standpunkt stehen, dass es
nicht schlimm ist, wenn schnelle Maschinen nicht ganz so
schnell sind, wenn stattdessen lahme Kisten viel besser werden :)
Also würde ich Test&Sprung wählen.

>> Der Unterschied zwischen der compilergenerierten und meiner
>> handgebastelten Variante liegt nur darin: Der Compiler rechnet
>> IMMER bis zum bitteren Ende, auch wenn das Resultat sowieso
>> zu groß wird.
>
> Was genau meinst du? Ein C Compiler bietet oft keine 128-Bit
> Multiplikation und die oft verfügbare 64-Bit Multiplikation
> liefert nur den unteren Teil, mit oder ohne Überlauf (mit
> Vorzeichen u.U. sogar einfach nur Unsinn).

Ich wollte nur dem beliebten Argument vorbauen, der Compiler
könnte sowieso alles besser.

Im konkreten Beispiel trifft das meiner Meinung nach nicht
unbedingt zu.

von Walter T. (nicolas)


Lesenswert?

Johann L. schrieb:
> Hier kann es zu einem Überlauf kommen.

Stimmt. An manchen Tagen sieht man nichts. Zum Kuckuck.

Jacko schrieb:
> Zum Programmstart zur Initialisierung???
>
> Da kann der Compiler doch noch ausrechnen,
> ob #VarA * #VarB < 2^64 ist...

Nicht alles, was zum Programmstart berechnet, wird, ist schon zur 
Kompilierzeit bekannt, z.B. Konfigurationsvariablen im EEPROM.


Johann L. schrieb:
> Weiters gibt es compilerspezifische Built-ins,

DANKE! Das ist hier genau das, was ich suche.

von Possetitjel (Gast)


Lesenswert?

Walter T. schrieb:

> Johann L. schrieb:
>> Weiters gibt es compilerspezifische Built-ins,
>
> DANKE! Das ist hier genau das, was ich suche.

Das ist ja unsportlich! :)

von Walter T. (nicolas)


Lesenswert?

Possetitjel schrieb:
> Das ist ja unsportlich! :)

Ich habe auch fast mehrere Sekunden darüber nachgedacht, die obige 
Variante auf 30-Bit-Häppchen umzubauen, die nicht überlaufen können, 
um...

Nein, ursprünglich war ich auf der Suche nach einer Standardlösung.

von Possetitjel (Gast)


Lesenswert?

Walter T. schrieb:

> Nein, ursprünglich war ich auf der Suche nach einer
> Standardlösung.

Ist schon in Ordnung.

Hast Du eigentlich mal daran gedacht, ein regelmäßiges
Preisausschreiben auszurichten? :)

von Walter T. (nicolas)


Lesenswert?

Possetitjel schrieb:
> Hast Du eigentlich mal daran gedacht, ein regelmäßiges
> Preisausschreiben auszurichten? :)



Bei den meisten Fragen, die ich hier stelle, gehe ich davon aus, daß es 
eine Standardfrage ist, die schon viele Menschen vor mir hatten und für 
die der Informatik kundige schon eine Standardlösung kennen.

Interessant ist es, wie selten diese Annahme stimmt. (Hier hat sie ja 
letztendlich doch gestimmt - schließlich gibt es diese Builtins nicht 
ohne Grund.)


Fragen, bei denen ich davon ausgehe, daß es keine Standardlösung gibt, 
stelle ich relativ selten, weil ich sowieso davon ausgehe, die Lösung 
selbst entwickeln zu müssen. Hier sind ein Kugelschreiber, viel Papier 
und eine Suchmaschine meine Helfer.


Als "Quereinsteiger" läßt sich das eine nur schwer vom anderen 
unterscheiden.

https://xkcd.com/1425/

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.