Wie summiere ich große Zahlen?

Lesezeit: 5 Minuten

Benutzer-Avatar
Timʘtei

Ich versuche zu rechnen 1 + 1 * 2 + 1 * 2 * 3 + 1 * 2 * 3 * 4 + ... + 1 * 2 * ... * n wo n ist die Benutzereingabe. Es funktioniert für Werte von n bis 12. Ich möchte die Summe berechnen für n = 13, n = 14 und n = 15. Wie mache ich das in C89? Wie ich weiß, kann ich verwenden unsigned long long int nur in C99 oder C11.

  1. Eingabe 13, Ergebnis 2455009817, erwartet 6749977113
  2. Eingabe 14, Ergebnis 3733955097, erwartet 93928268313
  3. Eingabe 15, Ergebnis 1443297817, erwartet 1401602636313

Mein Code:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    unsigned long int n;
    unsigned long int P = 1;
    int i;
    unsigned long int sum = 0;
    scanf("%lu", &n);
    for(i = 1; i <= n; i++)
    {
        P *= i;
        sum += P;
    }
    printf("%lu", sum);
    return 0;
}

  • Möglicherweise möchten Sie eine externe Bibliothek wie GMP (gmplib.org)

    – Federico Klez Culloca

    30. Mai 2017 um 10:25 Uhr


  • Ich verstehe die Ablehnung nicht. Die Anforderungen sind klar, und ein gut kompilierbares Beispiel wird mitgeliefert.

    – Bathseba

    30. Mai 2017 um 10:28 Uhr

  • @Bathsheba: Kein Forschungsaufwand ist ein gültiger DV-Grund. “unsigned long range” ist als Suchbegriff bei Google oder Wikipedia gar nicht so weit hergeholt!

    – zu ehrlich für diese Seite

    30. Mai 2017 um 10:32 Uhr


  • Okay. Ich formuliere eine Technik für größere ns. Gib mir etwas Zeit.

    – Pushan Gupta

    30. Mai 2017 um 11:09 Uhr

  • Ihr Programm liefert auf 64-Bit-Systemen die erwarteten Ergebnisse. Das heißt, es sei denn, Sie verwenden Windows.

    – Edgar Bonett

    30. Mai 2017 um 15:44 Uhr

Benutzer-Avatar
Basile Starynkevitch

In der Praxis wollen Sie einige Arithmetik mit beliebiger Genauigkeit (aka groß oder bignum) Bibliothek. Meine Empfehlung ist GMPlib aber da sind andere.

Versuchen Sie nicht, Ihre eigene Bignum-Bibliothek zu codieren. Es gibt effiziente und clevere Algorithmen, aber sie sind nicht intuitiv und schwer zu verstehen (Sie können ganze Bücher finden, die sich dieser Frage widmen). Darüber hinaus nutzen bestehende Bibliotheken wie GMPlib spezifische Maschinenanweisungen (z ADC -add with carry), die ein Standard-C-Compiler nicht ausgibt (aus reinem C-Code).

Wenn dies eine Hausaufgabe ist und Sie keinen externen Code verwenden dürfen, ziehen Sie zum Beispiel die Darstellung einer Zahl in Basis oder in Betracht Wurzel 1000000000 (eine Milliarde) und programmieren Sie sich die Operationen auf sehr naive Weise, ähnlich wie Sie es als Kind gelernt haben. Beachten Sie jedoch, dass es effizientere Algorithmen gibt (und dass echte Bignum-Bibliotheken sie verwenden).

Eine Zahl könnte in der Basis 1000000000 dargestellt werden, indem man ein Array von hat unsignedwobei jede eine “Ziffer” zur Basis 1000000000 ist. Sie müssen also Arrays verwalten (wahrscheinlich Heap-Zuweisungen mit malloc) und ihre Länge.

  • Einige gute Ratschläge hier. Ich verstehe die Ablehnung nicht, Zeit, sie umzukehren!

    – Bathseba

    30. Mai 2017 um 10:49 Uhr


  • @chtz: “Ich weiß nicht, ob die Implementierung einer BN-Bibliothek in einer interpretierten Sprache eine gute Idee ist.” – Das ist hier völlig off-topic, aber ab und zu können wir etwas Off-Topic-Spaß haben. Moderne leistungsstarke dynamische Optimierer sind äußerst nicht intuitiv. Zum Beispiel gibt es ein Ruby-Juwel zum Manipulieren von PSDs (Photoshop-Dateien). Es ist als hochoptimierte C-Erweiterung (für Ruby-Implementierungen, die sie unterstützen) und als “Fallback”-Implementierung in reinem, idiomatischem Ruby (für Implementierungen, die keine C-Erweiterungen unterstützen, wie z. B. Topaz, das ein AOT-Compiler ist, implementiert …

    – Jörg W Mittag

    30. Mai 2017 um 20:24 Uhr

  • … ECMAScript). Und diese reine Ruby-Fallback-Implementierung tut so ziemlich alles, was Sie sich vorstellen können, um einer Optimierung zu widerstehen. ZB dynamisches Aufrufen von Methoden aus Methodennamen, die in Laufzeitzeichenfolgen gespeichert sind, und solche Sachen. Schleifen über ein Array von Methodennamen und deren reflektierenden Aufruf. Sie könnten also denken, dass dies unmöglich schnell sein kann. Aber hier ist der Kicker: Genau Weil er ist in Ruby geschrieben, der TruffleRuby-Optimierungsinterpreter kann durch mehrere Inlining-, Spezialisierungs- und Optimierungsrunden das gesamte Testprogramm bis auf eine Konstante herunterkompilieren! Es ist …

    – Jörg W Mittag

    30. Mai 2017 um 20:27 Uhr

  • … deutlich schneller als die Verwendung der C-Erweiterung, da das Überschreiten der Ruby-C-Barriere kostspielig ist. Während TruffleRuby fröhlich zwischen dem Testprogramm (in Ruby geschrieben), der PSD-Bibliothek (in Ruby geschrieben) und den Ruby-Core-Datenstrukturen (in Ruby geschrieben) hin- und herpendelt, hat YARV nichts zu tun: YARV weiß nur, wie man Ruby ausführt schnell, aber der Ruby-Teil des Codes ist trivial. YARV hat keinen Einblick in die Ruby-Core-Datenstrukturen (in C geschrieben) oder die PSD-Bibliothek (in C geschrieben). GCC kann den Ruby-Code nicht optimieren, da es davon nichts weiß. Und jeder Aufruf von Ruby in die …

    – Jörg W Mittag

    30. Mai 2017 um 20:29 Uhr

  • … PSD-Bibliothek ist eine kostspielige Überschreitung der VM-Grenze. Letztendlich bringt Ihnen das Eliminieren dieser sprachübergreifenden Aufrufe alles und mehr zurück, als Sie durch das Schreiben des rechenintensiven Codes in Ruby verloren haben. Ich glaube also nicht, dass “Implementieren einer BN-Bibliothek in einer interpretierten Sprache” das ist das empörend. Die Möglichkeit, den rechenintensiven Code in die größere Anwendung zu integrieren, ist nicht zu unterschätzen.

    – Jörg W Mittag

    30. Mai 2017 um 20:32 Uhr

Sie könnten eine verwenden doubleinsbesondere wenn Ihre Plattform IEEE754 verwendet.

So ein double gibt Ihnen 53 Bit Genauigkeit, was bedeutet, dass ganze Zahlen bis zur 53. Potenz von 2 genau sind. Das ist gut genug für diesen Fall.

Wenn Ihre Plattform IEEE754 nicht verwendet, konsultieren Sie die Dokumentation zum übernommenen Gleitkommaschema. Es könnte angemessen sein.

  • Beachten Sie, dass dies im Gegensatz zu einer BigInt-Lösung ab einem bestimmten Punkt an Genauigkeit verliert.

    – BallpointBen

    30. Mai 2017 um 19:15 Uhr

  • In der Tat. Nach der 53. Potenz von 2 für IEEE754. Aber auch die eingebauten integralen Typen. Sie müssen also den richtigen Typ für Ihren Job auswählen.

    – Bathseba

    30. Mai 2017 um 19:34 Uhr

Ein einfacher Ansatz, wenn Sie knapp über der Grenze von MaxInt liegen, besteht darin, die Berechnungen modulo 10^n für ein geeignetes n durchzuführen, und Sie führen die gleiche Berechnung wie bei der Gleitkommaberechnung durch, wobei Sie jedoch alles durch 10^r dividieren. Das vorherige Ergebnis gibt Ihnen die ersten n Ziffern, während das letztere Ergebnis Ihnen die letzten Ziffern der Antwort gibt, wobei die ersten r Ziffern entfernt werden. Dann werden hier die letzten Ziffern durch Rundungsfehler ungenau, also solltest du ra etwas kleiner als n wählen. In diesem Fall wird es gut funktionieren, n = 9 und r = 5 zu nehmen.

1381810cookie-checkWie summiere ich große Zahlen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy