datalukas
Captain
- Registriert
- Dez. 2009
- Beiträge
- 3.628
Hallo liebe Community,
da ich viel mit Project Euler arbeite und man dafür teilweise auch sehr große Zahlen benötigt, und es mit VC++ etwas schwierig ist, für die aktuelle Version passende Bibliotheken zu finden, habe ich mir (auch aus Übungszwecken) mal selber eine Biginteger-Bibliothek geschrieben, die alle Methoden enthält, die ich bis jetzt brauchte (ist also bei weitem nicht vollständig).
Am Beispiel von Problem 25 bei Project Euler wird aber klar, wie langsam diese Umsetzung arbeitet. Die Bruteforce-Lösung dauert wahrscheinlich eine halbe Stunde (hab es nicht ganz durchrechnen lassen bis jetzt):
Die dafür nötigen Funktionen:
Add (per übeladenem +-Operator aufgerufen):
Zugrunde liegt der vector "digits" als Klassenvariable:
Wie kann man den Algorithmus noch verbessern?
Außerdem könnt ihr ruhig auch Verbesserungsvorschläge für den allgemeinen Programmierstil geben (Bezeichnungen, Algorithmen etc.).
Falls es jemanden interessiert, könnt ihr im Anhang die gesamte Bibliothek finden.
Abgesehen davon habe ich noch eine Frage zum Thema Programmiererfahrung. Im Moment bin ich 17, also in meiner Entscheidungsphase. Empfohlen werden ja hauptsächlich Aufgaben wie die bei Project Euler, aber fehlen hier für die Arbeit an einem kleinen Projekt, was hier auch oft zur Übung empfohlen wird, nicht noch "handfeste" Dinge wie die Kommunikation mit dem Betriebssystem oder GUI-Entwicklung?
Welche Dinge könnte man noch lernen, die einem den klassischen Programmieralltag näherbringen (dass das Studium sehr mathematisch und theoretisch ist, ist mir bewusst)?
Gruß
Datalukas
da ich viel mit Project Euler arbeite und man dafür teilweise auch sehr große Zahlen benötigt, und es mit VC++ etwas schwierig ist, für die aktuelle Version passende Bibliotheken zu finden, habe ich mir (auch aus Übungszwecken) mal selber eine Biginteger-Bibliothek geschrieben, die alle Methoden enthält, die ich bis jetzt brauchte (ist also bei weitem nicht vollständig).
Am Beispiel von Problem 25 bei Project Euler wird aber klar, wie langsam diese Umsetzung arbeitet. Die Bruteforce-Lösung dauert wahrscheinlich eine halbe Stunde (hab es nicht ganz durchrechnen lassen bis jetzt):
Code:
#include "stdafx.h"
#include <iostream>
#include "Biginteger.h"
int _tmain(int argc, _TCHAR* argv[])
{
vector<Biginteger> fibonacci(2);
fibonacci[0] = 1;
fibonacci[1] = 1;
while (fibonacci[1].getSize() < 1000)
{
fibonacci.push_back(fibonacci[1] + fibonacci[0]);
fibonacci.erase(fibonacci.begin());
}
system("Pause");
return 0;
}
Die dafür nötigen Funktionen:
Add (per übeladenem +-Operator aufgerufen):
Code:
Biginteger Biginteger::add(Biginteger firstsummand, Biginteger secondsummand)
{
Biginteger sum;
sum.setSize(firstsummand.getSize() > secondsummand.getSize() ? firstsummand.getSize() : secondsummand.getSize()); //Summe die Größe des größeren Summanden zuweisen
for (int i = 0; i < (firstsummand.getSize() > secondsummand.getSize() ? firstsummand.getSize() : secondsummand.getSize()); i++) //Schleife läuft bis zur letzten Ziffer des größeren Summanden
{
if (i >= (firstsummand.getSize() < secondsummand.getSize() ? firstsummand.getSize() : secondsummand.getSize())) //Falls i größer als der kleiner Summand ist wird, bekommt sum einfach die Ziffern des größeren zugewiesen
{
sum[i] += firstsummand.getSize() > secondsummand.getSize() ? firstsummand[i] : secondsummand[i];
}
else //Ansonsten werden jeweils die Ziffern zusammengezählt
{
sum[i] += firstsummand[i] + secondsummand[i];
}
if (sum[i] >= 10) //Zehnerstelle merken, falls das Ergebnis größer als 10 ist
carryAddMul(i, sum);
}
return sum;
}
Code:
carryAddMul (für das "Merken von Ziffern"):
void Biginteger::carryAddMul(int position, Biginteger& number)
{
if (number.getSize() <= position + 1) //Testen, ob number groß genug ist
number.push_back(0);
number[position + 1] += number[position] / 10; //Höherer Ziffer den Zehntel des gegebenen Wertes zuweisen
number[position] -= (number[position] / 10) * 10; //Zweite Ziffer der niederwertigen Ziffer entfernen
if (number[position + 1] >= 10) //Testen, ob höherwertige Ziffer mehr als eine Stelle hat
carryAddMul(position + 1, number); //rekursiv aufrufen, um die Stelle auf die jeweils höherwertige Ziffer zu übertragen
}
Zugrunde liegt der vector "digits" als Klassenvariable:
Code:
void Biginteger::setValue(vector<int> value)
{
digits = value;
}
Wie kann man den Algorithmus noch verbessern?
Außerdem könnt ihr ruhig auch Verbesserungsvorschläge für den allgemeinen Programmierstil geben (Bezeichnungen, Algorithmen etc.).
Falls es jemanden interessiert, könnt ihr im Anhang die gesamte Bibliothek finden.
Abgesehen davon habe ich noch eine Frage zum Thema Programmiererfahrung. Im Moment bin ich 17, also in meiner Entscheidungsphase. Empfohlen werden ja hauptsächlich Aufgaben wie die bei Project Euler, aber fehlen hier für die Arbeit an einem kleinen Projekt, was hier auch oft zur Übung empfohlen wird, nicht noch "handfeste" Dinge wie die Kommunikation mit dem Betriebssystem oder GUI-Entwicklung?
Welche Dinge könnte man noch lernen, die einem den klassischen Programmieralltag näherbringen (dass das Studium sehr mathematisch und theoretisch ist, ist mir bewusst)?
Gruß
Datalukas