Ich sehe, dass viele Leute die Frage nach dem Überlauf beantwortet haben, aber ich wollte auf sein ursprüngliches Problem eingehen. Er sagte, das Problem sei, eine b \=c so, dass alle Ziffern ohne Wiederholung verwendet werden. Ok, das ist nicht das, was er in diesem Beitrag gefragt hat, aber ich denke immer noch, dass es notwendig war, die obere Schranke des Problems zu studieren und zu dem Schluss zu kommen, dass er niemals einen Überlauf berechnen oder erkennen muss (Anmerkung: Ich bin nicht gut in Mathe, also habe ich das Schritt für Schritt gemacht, aber das Endergebnis war so einfach, dass es eine einfache Formel haben könnte).
Der wichtigste Punkt ist, dass die Obergrenze, die das Problem für a, b oder c erfordert, 98.765.432 beträgt. Wie auch immer, wir beginnen damit, das Problem in einen trivialen und einen nicht-trivialen Teil aufzuteilen:
- x 0 \== 1 (alle Permutationen von 9, 8, 7, 6, 5, 4, 3, 2 sind Lösungen)
- x 1 \== x (keine Lösung möglich)
- 0 b \== 0 (keine Lösung möglich)
- 1 b \== 1 (keine Lösung möglich)
- a b , a > 1, b > 1 (nicht trivial)
Jetzt müssen wir nur noch zeigen, dass keine andere Lösung möglich ist und nur die Permutationen gültig sind (und dann ist der Code, um sie zu drucken, trivial). Wir gehen zurück zur oberen Schranke. Eigentlich ist die Obergrenze c 98.765.432. Es ist die obere Schranke, weil es die größte Zahl mit 8 Ziffern ist (10 Ziffern insgesamt minus 1 für jedes a und b). Diese obere Schranke gilt nur für c, weil die Schranken für a und b wegen des exponentiellen Wachstums viel niedriger sein müssen, wie wir berechnen können, wenn wir b von 2 bis zur oberen Schranke variieren:
9938.08^2 == 98765432
462.241^3 == 98765432
99.6899^4 == 98765432
39.7119^5 == 98765432
21.4998^6 == 98765432
13.8703^7 == 98765432
9.98448^8 == 98765432
7.73196^9 == 98765432
6.30174^10 == 98765432
5.33068^11 == 98765432
4.63679^12 == 98765432
4.12069^13 == 98765432
3.72429^14 == 98765432
3.41172^15 == 98765432
3.15982^16 == 98765432
2.95305^17 == 98765432
2.78064^18 == 98765432
2.63493^19 == 98765432
2.51033^20 == 98765432
2.40268^21 == 98765432
2.30883^22 == 98765432
2.22634^23 == 98765432
2.15332^24 == 98765432
2.08826^25 == 98765432
2.02995^26 == 98765432
1.97741^27 == 98765432
Beachten Sie zum Beispiel die letzte Zeile: Dort steht, dass 1,97^27 ~98M. Also, zum Beispiel, 1^27 == 1 und 2^27 == 134.217.728 und das ist keine Lösung, weil es 9 Ziffern hat (2 > 1.97, also ist es eigentlich größer als das, was getestet werden sollte). Wie man sieht, sind die verfügbaren Kombinationen zum Testen von a und b wirklich klein. Für b == 14 müssen wir 2 und 3 ausprobieren. Für b == 3 fangen wir bei 2 an und hören bei 462 auf. Alle Ergebnisse sind garantiert kleiner als ~98M.
Testen Sie nun alle obigen Kombinationen und suchen Sie nach denjenigen, bei denen sich keine Ziffern wiederholen:
['0', '2', '4', '5', '6', '7', '8'] 84^2 = 7056
['1', '2', '3', '4', '5', '8', '9'] 59^2 = 3481
['0', '1', '2', '3', '4', '5', '8', '9'] 59^2 = 3481 (+leading zero)
['1', '2', '3', '5', '8'] 8^3 = 512
['0', '1', '2', '3', '5', '8'] 8^3 = 512 (+leading zero)
['1', '2', '4', '6'] 4^2 = 16
['0', '1', '2', '4', '6'] 4^2 = 16 (+leading zero)
['1', '2', '4', '6'] 2^4 = 16
['0', '1', '2', '4', '6'] 2^4 = 16 (+leading zero)
['1', '2', '8', '9'] 9^2 = 81
['0', '1', '2', '8', '9'] 9^2 = 81 (+leading zero)
['1', '3', '4', '8'] 3^4 = 81
['0', '1', '3', '4', '8'] 3^4 = 81 (+leading zero)
['2', '3', '6', '7', '9'] 3^6 = 729
['0', '2', '3', '6', '7', '9'] 3^6 = 729 (+leading zero)
['2', '3', '8'] 2^3 = 8
['0', '2', '3', '8'] 2^3 = 8 (+leading zero)
['2', '3', '9'] 3^2 = 9
['0', '2', '3', '9'] 3^2 = 9 (+leading zero)
['2', '4', '6', '8'] 8^2 = 64
['0', '2', '4', '6', '8'] 8^2 = 64 (+leading zero)
['2', '4', '7', '9'] 7^2 = 49
['0', '2', '4', '7', '9'] 7^2 = 49 (+leading zero)
Keiner von ihnen entspricht dem Problem (was auch am Fehlen von '0', '1', ..., '9' zu erkennen ist).
Es folgt ein Beispielcode, der diese Aufgabe löst. Beachten Sie auch, dass er in Python geschrieben ist, nicht weil er beliebig genaue Zahlen benötigt (der Code berechnet nichts, was größer als 98 Millionen ist), sondern weil wir herausgefunden haben, dass die Anzahl der Tests so klein ist, dass wir eine Hochsprache verwenden sollten, um ihre eingebauten Container und Bibliotheken zu nutzen (beachten Sie auch: der Code hat 28 Zeilen).
import math
m = 98765432
l = []
for i in xrange(2, 98765432):
inv = 1.0/i
r = m**inv
if (r < 2.0): break
top = int(math.floor(r))
assert(top <= m)
for j in xrange(2, top+1):
s = str(i) + str(j) + str(j**i)
l.append((sorted(s), i, j, j**i))
assert(j**i <= m)
l.sort()
for s, i, j, ji in l:
assert(ji <= m)
ss = sorted(set(s))
if s == ss:
print '%s %d^%d = %d' % (s, i, j, ji)
# Try with non significant zero somewhere
s = ['0'] + s
ss = sorted(set(s))
if s == ss:
print '%s %d^%d = %d (+leading zero)' % (s, i, j, ji)
31 Stimmen
Informationen, die zu diesem Thema nützlich sein können: Kapitel 5 von "Secure Coding in C and C++" von Seacord - http://www.informit.com/content/images/0321335724/samplechapter/seacord_ch05.pdf SafeInt-Klassen für C++ - http://blogs.msdn.com/david_leblanc/archive/2008/09/30/safeint-3-on-codeplex.aspx - http://www.codeplex.com/SafeInt IntSafe-Bibliothek für C: - [ blogs.msdn.com/michael_howard/archiv
3 Stimmen
Seacord's Secure Coding ist eine großartige Ressource, aber verwenden Sie nicht IntegerLib. Siehe blog.regehr.org/archives/593 .
45 Stimmen
Die gcc-Compileroption
-ftrapv
führt dazu, dass er bei einem (vorzeichenbehafteten) Integer-Überlauf einen SIGABRT erzeugt. Siehe aquí .3 Stimmen
Das beantwortet zwar nicht die Frage des Überlaufs, aber eine andere Möglichkeit, das Problem anzugehen, wäre die Verwendung einer BigNum-Bibliothek wie GMP um zu gewährleisten, dass Sie immer über genügend Präzision verfügen. Sie müssen sich keine Sorgen über einen Überlauf machen, wenn Sie im Voraus genügend Ziffern zuweisen.
1 Stimmen
Die von @HeadGeek in seiner Antwort gegebenen Informationen entsprechen ziemlich genau dem, was ich auch sagen würde. Allerdings mit einem Zusatz. Die Art und Weise, wie Sie die Überfliegung bei einer Multiplikation jetzt erkennen, ist wahrscheinlich die schnellste. Auf ARM, wie ich in HeadGeeks Antwort kommentiert habe, können Sie die
clz
Anweisung oder die__clz(unsigned)
Funktion, um den Rang der Zahl zu bestimmen (wo ihr höchstes Bit ist). Da ich nicht weiß, ob diese Funktion auf x86 oder x64 verfügbar ist, gehe ich davon aus, dass sie es nicht ist, und sage, dass die Ermittlung des höchstwertigen Bits im schlimmsten Falllog(sizeof(int)*8)
Anweisungen.0 Stimmen
Eine Möglichkeit zur statischen Erkennung von Integer-Überläufen (mit False Positives): usenix.org/conference/osdi12/technical-sessions/presentation/