Wurzelberechnung

Code-Stücke können hier veröffentlicht werden.
Antworten
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

1 Funktion zur Berechnung der n-ten Wurzel aus x
und eine zur Berechnung der 2. Wurzel aus x

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import division
from decimal import Decimal, getcontext

def calculate(wexp, radi, acc=50):
    '''Berechnung mithilfe der numerischen Berechnung
    wexp = Wurzelexponent, radi = Radikand''' 
    getcontext().prec = acc
    y = 2
    wexp = Decimal(str(wexp))
    radi = Decimal(str(radi))
    while True:
        old_y = y
        y = ((wexp - 1) * y**wexp + radi) / (wexp * y**(wexp-1))
        if old_y == y:
            break
    return y

def calculate_newton(radi, acc=50):
    ''' Berechnung mithilfe des Newton-Verfahrens, nur f�r 
    die 2. Wurzel!'''
    getcontext().prec = acc
    y = 2
    einhalb = Decimal('0.5')
    radi = Decimal(str(radi))
    while True:
        old_y = y
        y = einhalb * (y + (radi/y))
        if old_y == y:
            break
    return y

if __name__ == '__main__':
    print calculate(2, 2, 10)
    print calculate_newton(2)
the more they change the more they stay the same
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dav1d hat geschrieben:1 Funktion zur Berechnung der n-ten Wurzel aus x

Code: Alles auswählen

>>> from decimal import Decimal
>>> nroot = lambda x,n:(Decimal(x).ln()/n).exp()
>>> print nroot(12345,6)
4.807454497944548271506999339
Dav1d hat geschrieben:und eine zur Berechnung der 2. Wurzel aus x

Code: Alles auswählen

>>> print Decimal(12345).sqrt()
111.1080555135405112450044387
Im übrigen ist "calculate" ein ausgesprochen schlechter Name für eine Funktion, weil es nichts darüber aussagt, WAS berechnet wird.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Den gezeigen Code könnte man auch nochweiter verallgemeinern:

Code: Alles auswählen

def calculate(wexp, radi, acc=50):
    wexp = Decimal(str(wexp))
    radi = Decimal(str(radi))

    return iterative(2,
		     lambda y: ((wexp-1)*y**wexp + radi)/(wexp * y**(wexp-1)),
		     acc)

def calculate_newton(radi, acc=50):
    half = Decimal('0.5')
    radi = Decimal(str(radi))

    return iterative(2, lambda y: half * (y + (radi/y)), acc)

def iterative(value, func, acc=50):
    getcontext().prec = acc

    while True:
        old_value = value
        value = func(value)

        if value == old_value:
            return value
Das Leben ist wie ein Tennisball.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

numerix, ja das stimmt wohl, da es aber nur kleine Beispiele sind finde ich das Ok

EyDu, das gefällt mir ;)
the more they change the more they stay the same
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dav1d hat geschrieben:numerix, ja das stimmt wohl, da es aber nur kleine Beispiele sind finde ich das Ok
Den Satz verstehe ich nicht.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

numerix hat geschrieben:Im übrigen ist "calculate" ein ausgesprochen schlechter Name für eine Funktion, weil es nichts darüber aussagt, WAS berechnet wird.
Ich finde das nicht (nichtssagender Name) so schlimm, weil es nur ein kleines Beispiel ist
the more they change the more they stay the same
lunar

Dav1d hat geschrieben:
numerix hat geschrieben:Im übrigen ist "calculate" ein ausgesprochen schlechter Name für eine Funktion, weil es nichts darüber aussagt, WAS berechnet wird.
Ich finde das nicht (nichtssagender Name) so schlimm, weil es nur ein kleines Beispiel ist
Wo ist dann die Grenze zwischen „kleinem Beispiel“ (nicht so schlimm) und „produktivem Code“ (sehr schlimm!)? ;)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dav1d hat geschrieben:
numerix hat geschrieben:Im übrigen ist "calculate" ein ausgesprochen schlechter Name für eine Funktion, weil es nichts darüber aussagt, WAS berechnet wird.
Ich finde das nicht (nichtssagender Name) so schlimm, weil es nur ein kleines Beispiel ist
Was heißt schon "schlimm". Es gibt eigentlich keinen Grund dafür, einer Funktion einen nichtssagenden Namen zu geben, egal wie kurz oder lang ein Beispiel ist. Man sollte es sich zur guten Angewohnheit machen, bei der Wahl von Bezeichnernamen gute Entscheidungen zu treffen, weil es die Lesbarkeit von Code erhöht - auch für einen selbst, wenn man nach einigen Wochen wieder mal in den Code hineinschaut.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

lunar hat geschrieben:Wo ist dann die Grenze zwischen „kleinem Beispiel“ (nicht so schlimm) und „produktivem Code“ (sehr schlimm!)? ;)
Ich habe den Code gepostet, damit andere Teile aus ihm weitervwenden können, wenn der Code aber "groß" wird, in Richtung Projekt dann ist es für aussenstehende leichter zu erknennen was "passiert"

@numerix, Der Name unter dem ich die Datei gespeichert habe sagt mir um was es geht ;)
Ich verstehe was du meinst und ich merks mir, mir ist in dem Moment nichts besseres eingefallen
Wie wärs mit calculate_root?
the more they change the more they stay the same
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dav1d hat geschrieben:Wie wärs mit calculate_root?
Das ist doch schon ein deutlicher Fortschritt.

Grundsätzlich hilfreich ist der Wechsel der Perspektive: Lässt sich aus Sicht dessen, der den Code nicht selbst geschrieben hat, allein anhand des Funktionsnamens erkennen, was die Funktion macht? Kannst du diese Frage mit "ja" beantworten, dann spricht das für die Wahl des Bezeichners (ist aber nicht das einzige Kriterium!). Da "root" nicht eindeutig ist - welche Wurzel soll berechnet werden? - würde ich die Bezeichnung noch weiter spezifieren. Und statt calculate reicht in der Regel auch "calc". Man könnte das "calc" natürlich auch ganz weglassen, aber dann lässt sich aus dem Namen nicht mehr erschließen, dass hier etwas getan wird.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

die 1. Funktion berechnet jede Wurzel also trifft der Name doch zu
the more they change the more they stay the same
BlackJack

@Dav1d: Die Frage ist, ob man das weiss wenn man den Namen liest. `calculate_nth_root()` oder so wäre deutlicher. Denn wenn die Leute nur "Wurzel" lesen, nehmen sie in aller Regel "Quadratwurzel" an, denn die ist, zumindest umgangssprachlich, normalerweise gemeint, wenn man's nicht näher spezifiziert.
Gabelmensch
User
Beiträge: 79
Registriert: Montag 12. Oktober 2009, 11:50

In wieviele Teile wollt ihr das Haar noch spalten?
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Gabelmensch hat geschrieben:In wieviele Teile wollt ihr das Haar noch spalten?
Das ist ganz und gar keine Haarspalterei. Letztenendes geht es hier um die Lesbarkeit von Quelltexten und das kann man gar nicht hoch genug schätzen.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Dav1d hat geschrieben:Wie wärs mit calculate_root?
Also ich habe noch in keiner Sprache eine Funktion gesehen, die mit "calculate_" beginnt.
calculate_sin, calculate_abs, etc. Das würde mich nerven. Daß da was kalkuliert wird, ist doch klar. Nenn sie doch einfach nthroot. Jeder würde damit klarkommen. Warum immer so kompliziert.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Die 1. heist jetzt nth_root, die 2. sqrt_newton ;)
the more they change the more they stay the same
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dav1d hat geschrieben:Die 1. heist jetzt nth_root, die 2. sqrt_newton ;)
Dann kannst du ja jetzt anfangen, dich um die Performance zu kümmern. :D

Du könntest beispielsweise √2 auf möglichst viele Nachkommastellen berechnen. Was dein Algorithmus in punkto Geschwindigkeit zu bieten hat, kannst du dann z.B. bei SPOJ messen ...
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

mal noch ne Frage,

warum nicht einfach :

Code: Alles auswählen

>>> from __future__ import division
>>> 12345**(1/6)
4.8074544979445477
nehmen??
Der einzige Grund, der mir einfiele ist die Genauigkeit ab der 10. Stelle nach dem Komma....
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

mathi hat geschrieben:Der einzige Grund, der mir einfiele ist die Genauigkeit ab der 10. Stelle nach dem Komma....
Ob es jetzt genau die 10. Stelle ist, sei mal dahingestellt, aber: Genau das ist der Grund.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ja, das ist's ;)

Mit dem Decimal-Modul, kann ich die Genauigkeit genau einstellen

Code: Alles auswählen

getcontext().prec = 30 # 30 "Stellen"
the more they change the more they stay the same
Antworten