Seite 2 von 3
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Mittwoch 8. Oktober 2014, 15:00
von plotxy
Code: Alles auswählen
from mpmath import mp
import time
mp.dps = 1000000
euler = 1
x = 1
n = 1
i = 0
zeit1 = (time.strftime("%d.%m.%Y %H:%M:%S:%MS"))
test = time.clock()
while n < 200000:
x = mp.fmul(x,n)
euler = euler + mp.fdiv(1,x)
n = n + 1
if time.clock() - test > 1800:
f = open("tmp.txt","w")
f.truncate()
f.write(str(euler))
f.close()
test = time.clock()
print(euler)
euler2 = euler + mp.fdiv(1,x*n)
print(euler2)
zeit2 =(time.strftime("%d.%m.%Y %H:%M:%S:%MS"))
eulerdiv = 0
eulerdiv = mp.fsub(euler2,euler)
print(eulerdiv)
if eulerdiv > 0:
while eulerdiv < 0.1:
eulerdiv = eulerdiv * 10
i += 1
print(i)
zeit2 =(time.strftime("%d.%m.%Y %H:%M:%S:%MS"))
print(zeit1)
print(zeit2)
was sagt ihr dazu ?
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Mittwoch 8. Oktober 2014, 15:17
von Sirius3
@plotxy: warum die while-Schleife? Wenn Du feste Grenzen hast, dann nimm doch for.
Wenn Du Dateien mit 'w' öffnest, werden die automatisch auf 0 Bytes gestaucht, ein truncate ist überflüssig. Öffne Dateien mit dem with-Statement.
Hab mpmath noch nie benutzt, sieht aber ziemlich unpythonisch aus und scheint auch noch lahm zu sein, wenn Du tatsächlich mit dem Code mehr als 15 Minuten Rechenzeit hast, weil ich die mit dem quasi gleichen Algorithmus erreicht habe.
Zum Berechnen der Genauigkeit hilft Dir vielleicht der 10er Logarithmus.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Mittwoch 8. Oktober 2014, 15:27
von plotxy
Welche bibliothek hast du denn genommen, um die entsprechende genauigkeit zu erreichen ?
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Mittwoch 8. Oktober 2014, 15:29
von BlackJack
@plotxy: ``f.truncate()`` ist überflüssig. Dateien sollte man zusammen mit der ``with``-Anweisung öffnen. Die ``while``-Schleife sollte wohl eigentlich eine ``for``-Schleife sein.
Namen sollte man erst definieren wenn man sie auch braucht und nicht alle am Anfang. Das `i` hatte mich zum Beispiel erst ein wenig verwirrt weil das erst sehr viel weiter unten auch tatsächlich verwendet wird.
`test` ist kein guter Namen für den Wert.
Funktionen machen den Quelltext nicht nur übersichtlicher sondern auch geringfügig schneller weil lokale Namen schneller aufgelöst werden als welche auf Modulebene.
Muss man `mpmath` tatsächlich als Funktionen verwenden? Sind das keine eigenen Typen mit überladenen Operatoren? Ich würde wahrscheinlich auch deutlich mehr mit Generatoren arbeiten.
Die Klammern um den Wert bei `zeit2` sind überflüssig. Die Zuweisung von 0 an `eulerdiv` ebenfalls, sowie die erste Zuweisung an `zeit2` die überhaupt nicht verwendet wird. Ausserdem sollte das wohl `eulerdiff` heissen!?
Eventuell gibt es eine schnellere Methode um an die Zehnerpotenz zu kommen als die Zahl tatsächlich wiederholt mit 10 zu multiplizieren!?
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Mittwoch 8. Oktober 2014, 15:30
von EyDu
Ich würde mal behaupten, dass das einfach viel zu viele Divisionen sind. Dadurch verlierst du die ganze Performance von Integern. Hier mal mein Ansatz:
Code: Alles auswählen
import decimal
import sys
import time
def euler_fraction(N):
numerator = denominator = 1
for i in xrange(1, N):
numerator = i*numerator + 1
denominator *= i
return numerator, denominator
def main():
N = 205211
PRECISION = 1000000
filename = sys.argv[1]
start = time.time()
numerator, denominator = map(decimal.Decimal, euler_fraction(N))
decimal.getcontext().prec = PRECISION
with open(filename, "w") as fp:
fp.write(str(numerator/denominator))
end = time.time()
print "total:", end - start, "seconds"
if __name__ == "__main__":
main()
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Mittwoch 8. Oktober 2014, 16:36
von plotxy
Ich habe mal deinen Ansatz genommen und ein wenig umgeschrieben. Er schaffte es in 8 sec stat 42.
also lag es bei mir wirklich am zu komplizierten code. Danke für die hilfe.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Mittwoch 8. Oktober 2014, 16:37
von EyDu
Nicht ganz so schnell wie Mathematica, aber die C++-Lösung braucht bei mir keine 20 Sekunden:
Code: Alles auswählen
#include <iostream>
#include <fstream>
#include <boost/multiprecision/gmp.hpp>
typedef boost::multiprecision::mpf_float Float;
typedef boost::multiprecision::mpz_int Int;
typedef boost::multiprecision::mpq_rational Rational;
Rational euler_fraction(
const unsigned int n)
{
Int numerator = 1;
Int denominator = 1;
for(unsigned int i=1; i<n; ++i) {
numerator = numerator*i + 1;
denominator *= i;
}
return Rational(numerator, denominator);
}
int main(
int argc,
char **argv)
{
static const unsigned int PRECISION = 1000000;
static const unsigned int N = 205211;
Float::default_precision(PRECISION);
std::ofstream stream(argv[1]);
stream.precision(PRECISION);
stream << Float(euler_fraction(N));
stream.close();
return 0;
}
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Montag 13. Oktober 2014, 21:01
von plotxy
@EyDu gibt es eine möglichkeit numerator und denuminator parallel auszurechnen und dann anschließend zu subtrahieren ?
somit würde man nur die hälfte der rechenzeit brauchen.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Montag 13. Oktober 2014, 22:16
von EyDu
Ja, du könntest das multiprocessing-Modul verwenden. Damit wird es noch etwas schneller. Es werden bei mir aus fast genau vier Minuten knapp unter drei. Allerdings solltest du mal genauer nachschauen, was nun tatsächlich welchen Anteil an Zeit frisst. Das umwandeln in Decimal und die Division machen sicher einen riesen Batzen aus.
Code: Alles auswählen
import multiprocessing as mp
import operator
def calculate_numerator(N, result):
numerator = 1
for i in xrange(1, N):
numerator = i*numerator + 1
result.put(numerator)
def calculate_numerator2(N, result):
result.put(reduce(operator.mul, xrange(1, N)))
def calculate_denominator(N, result):
denominator = 1
for i in xrange(1, N):
denominator *= i
result.put(denominator)
def calculate_denominator2(N, result):
result.put(math.factorial(N))
def euler_parallel(N):
numerator = mp.Queue()
denominator = mp.Queue()
pn = mp.Process(target=calculate_numerator2, args=(N, numerator))
pd = mp.Process(target=calculate_denominator2, args=(N, denominator))
pn.start()
pd.start()
return numerator.get(), denominator.get()
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 09:14
von Sirius3
Meine Variante, die gleich von großen Zahlen nach kleinen rechnet, spart sich die zweite Multiplikation gleich. Aber einen großen Teil der Zeit verschlingt die abschließende Division.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 14:51
von plotxy
Code: Alles auswählen
from mpmath import mp
from math import log10, factorial
import time
from multiprocessing import Process, Queue
def get_p(n, queue):
print("get_p ...")
p = 1
for i in range(1, n+1):
p = i*p + 1
queue.put(p)
print("get_p done!")
def get_q(n, queue):
print("get_q ...")
q = factorial(n)
queue.put(q)
print("get_q done!")
def get_p_q_multiprocess(n):
p_queue = Queue()
q_queue = Queue()
p_process = Process(target=get_p, args=(n, p_queue))
q_process = Process(target=get_q, args=(n, q_queue))
p_process.start()
q_process.start()
q = q_queue.get()
p = p_queue.get()
q_process.join()
p_process.join()
return p, q
def main():
n = 1*10**4
t1 = time.time()
p, q = get_p_q_multiprocess(n)
t2 = time.time()
print("calc p and q in"(t2-t1))
p_mag_10 = int(log10(p))+1
prec = p_mag_10
print("precicion:", prec)
mp.dps = prec + 10
time3 = time.time()
euler = mp.fdiv(p, q)
time4 = time.time()
print(time4 - time3)
s = str(euler)[:prec+1]
print(s[3])
main()
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 14:54
von plotxy
@EyDu wenn ich den prozess starte passiert nichts. der prozess ist zwar unter taksmaneger zu finden. Doch nur mit einer auslastung von max 00.03. woran liegt das ? bei meinem bruder funktioniert es auch.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 14:59
von BlackJack
@plotxy: Das Modul mit dem das Programm gestartet wird muss zumindest unter Windows importiert werden können ohne das dabei irgendwas ”passiert”. Sonst funktioniert `multiprocessing` nicht. Du musst den `main()`-Aufruf also mit einem ``if __name__ == '__main__':`` schützen.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 16:29
von plotxy
@EyDu viel dank! jetzt läuft es echt schön. (:
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 20:00
von Leonidas
Hmm, das habe ich jetzt schnell hingehackt aber von der Performance ist der Code recht unterirdisch
Code: Alles auswählen
let one = Gmp.F.from_int 1
let prec = 1_000_000
let fmul = Gmp.F.mul_prec_ui ~prec
let fdiv = Gmp.F.div_prec ~prec
let fadd = Gmp.F.add_prec ~prec
let to_string = Gmp.F.to_string_base_digits ~base:10 ~digits:1000
let f () =
let x = ref one in
let euler = ref one in
for n = 1 to 205_211 do
x := fmul !x n;
euler := fadd !euler @@ fdiv one !x;
done;
print_endline @@ to_string !euler
let _ =
f ()
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 20:40
von Sirius3
@Leonidas: warum gehst Du nur bis 20000! ?
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 21:52
von Leonidas
Sirius3 hat geschrieben:@Leonidas: warum gehst Du nur bis 20000! ?
Versehen, hab das von
hier übernommen und eine Null übersehen. In dem Fall ist die Performance noch viel schlimmer, was ja eigentlich gar nicht sein kann. Frag mich ob das Gmp-Binding so unterirdisch ist oder mein Code. Vielleicht mal Profiler anwerfen.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 22:50
von EyDu
Ich tippe mal auf deinen Code

Die Berechnung mit Floats sollte eine Ecke langsamer sein als mit Integern und die ganzen rechenintensiven Divisionen ziehen das ganze wahrscheinlich so richtig runter. Es reicht eine Division ganz am Ende. Hinzu kommt dann noch das Problem der Genauigkeit. Du rechnest zwar mit einer Millionen Stellen Genauigkeit pro Operation, das garantiert aber keine korrekten eine Millionen Stellen im Endergebnis.
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 23:02
von EyDu
In 20 Sekunden kann man sich ja nicht mal mehr einen Kaffee holen
Code: Alles auswählen
#include <iostream>
#include <fstream>
#include <thread>
#include <boost/multiprecision/gmp.hpp>
typedef boost::multiprecision::mpf_float Float;
typedef boost::multiprecision::mpz_int Int;
typedef boost::multiprecision::mpq_rational Rational;
void numerator_thread(
const unsigned int n,
Int & numerator)
{
numerator = 1;
for(unsigned int i=1; i<n; ++i) {
numerator = numerator*i + 1;
}
}
void denominator_thread(
const unsigned int n,
Int & denominator)
{
denominator = 1;
for(unsigned int i=1; i<n; ++i) {
denominator *= i;
}
}
Rational euler_parallel(
const unsigned int n)
{
Int numerator = 1;
Int denominator = 1;
std::thread nt(&numerator_thread, n, std::ref(numerator));
std::thread dt(&denominator_thread, n, std::ref(denominator));
nt.join();
dt.join();
return Rational(numerator, denominator);
}
int main(
int argc,
char **argv)
{
static const unsigned int PRECISION = 1000000;
static const unsigned int N = 205211;
Float::default_precision(PRECISION);
std::ofstream stream(argv[1]);
stream.precision(PRECISION);
stream << Float(euler_parallel(N));
stream.close();
return 0;
}
Re: aktelle Werte in einer while schleife ausgeben
Verfasst: Dienstag 14. Oktober 2014, 23:12
von Leonidas
EyDu hat geschrieben:Ich tippe mal auf deinen Code

Da hast du durchaus recht, das war aber auch eine runde missverstehen dabei. Hatte den Eindruck dass
Code: Alles auswählen
from mpmath import mp
mp.dps = 1000000
euler = 1
x = 1
n = 1
while n < 205211:
x = mp.fmul(x,n)
euler = euler + mp.fdiv(1,x)
n = n + 1
print(euler)
in 40 Sekunden abläuft.