Mantissenlänge varieren

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Gelöscht2200

Ich soll ein Python-Programm schreiben mit einer Rekursiven Funktion, dabei soll die Manissenlänge m varieren zwischen 6 und 20 in 2er Schritten. Das ganze soll das Modul decimal benutzen. Wie implementiert man die Variation der Mantissenlänge.

Hier ist mein Code soweit

Code: Alles auswählen

from __future__ import division
from sympy import *

import numpy as np
import decimal

D = decimal.Decimal

n = D("1")
a = D("10")
m = D("6")              # mantissa lenght
l = 10
y = D("0")


for i in range(1,l):
        n += 1
        y = 1/n - a * y
        print ("y: ", y)
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

loyloep hat geschrieben:Ich soll ein Python-Programm schreiben mit einer Rekursiven Funktion, dabei soll die Mantissenlänge m varieren zwischen 6 und 20 in 2er Schritten. Das ganze soll das Modul decimal benutzen.
Die Mantisse bezeichnet die Zahl der signifikanten Stellen eines floats. Eine Mantisse gibt es bei decimal nicht, am nächsten käme dem sinngemäß die 'precision', insofern ich Deine Beschreibung korrekt interpretiere. Infos zur 'precision' findest Du in der Dokumentation zu decimal. Möglicherweise ist in Deiner Aufgabe aber auch die Zahl der anzuzeigenden Nachkommastellen gemeint und nicht die Präzision.
Gelöscht2200

In der Aufgabe ist in der Tat explizit von der Mantissenlänge die Rede. Ich muss da noch mal Rücksprache mit meinem Dozenten halten.

Danke soweit für Deine aufklärende Antwort.
Gelöscht2200

Also mein Dozent hat mir den Link zum Wikipedia -EIntrag für "Mantisse" gegeben.

https://de.wikipedia.org/wiki/Mantisse


Gemäß dieser Dratsellung würde die Mantisse der Präzisions-Funktion in der decimal.Decimal-Darstellung.

Es gibt in Python den Befehl:

Code: Alles auswählen

ctx.prec
, mit dem sich die Genauigkeit (Präzision) verändern lässt. Wie baue ich nun diesen Befehl in mein Programm ein, damit die Präzision variert wird zwischen 6 und 20 in zweier Schritten? Eine -Schleife vielleicht? Wie genau sieht die aus?
BlackJack

@loyloep: Ich glaube das ist Teil Deiner Hausaufgabe das herauszufinden. Es gibt da so etwas was sich Dokumentation nennt: https://docs.python.org/2/library/decim ... xt-objects

Da gibt's Beschreibungen und Beispiele, Anmerkungen, Rezepte, und eine FAQ.

Trotzdem als Stichwort: `localcontext()`
Gelöscht2200

Danke für den Hinweis! Ich habe jetzt den Code abgeändert. Allerdings bleibt das Programm in der letzten Zeile hängen mit der Begründung

Code: Alles auswählen

integral()
take 3 positional argument, but 4 were given. Das verstehe ich nicht. Ich habe ja nur drei argumente in

Code: Alles auswählen

integral()
gegeben. Hat jemand eine Idee warum hier eine solche Fehlermeldung auftaucht.

Code: Alles auswählen

# BZQ 2 (Projektpraktikum 1) 
# Serie 1
# Autor: Bianca Drefahl, 


from __future__ import division
from sympy import *

import numpy as np
import decimal

D = decimal.Decimal


ctx = decimal.getcontext()



class Integral(object):    # Klasse, deren Objekte Skalare sind 

        def __init__(self, a, n, m):       # Konstruktor
                self.Variable = a  
                self.Wiederholung = n 
                self.Mantisse = m
        

        def integral(a,n,m):            # Methode (Berechnung der Integral-Annäherungsformel)
                ctx.prec=m
                y =  D("0")
                for i in range(1,n):
                        n += 1
                        y = 1/n - a * y
                print ("y: ", y)


objekt = Integral(10,10,6)

objekt.integral(10,10,6)
Gelöscht2200

Ich habe die Lösung für dieses Problem gefunden.
Gelöscht2200

So das Programm läuft nun durch. Allerdings kann ich die Mantissenlänge nicht ändern und ich bin mir auch nicht sicher , ob das ganze in Decimal dargestellt wird.

Code: Alles auswählen

from __future__ import division
from sympy import *

import numpy as np
import decimal

#D = decimal.Decimal


ctx = decimal.getcontext()



class Integral(object):    # Klasse, deren Objekte Skalare sind 

        def __init__(self, a, n, m):       # Konstruktor
                self.Variable = a  
                self.Wiederholung = n 
                self.Mantisse = m
        

        def integral(self,a,n,m):            # Methode (Berechnung der Integral-Annäherungsformel)
                ctx.prec=m
                y =  0
                for i in range(1,n):
                        n += 1
                        y = 1/n - a * y
                        print ("y: ", y)


objekt = Integral(10,10,2)

objekt.integral(10,10,2)
Gelöscht2200

Ich habe eine Lösung für die zwei Probleme gefunden.
Gelöscht2200

Ein weiterer Aufgabenbestandteil sagt: Stellen Sie eine Funktion readJson zum Einlesen von Daten aus einer Datei im
json Format zur Verfugung. Inputparameter ist ein File Objekt. ¨
Stellen Sie die notwendigen Daten in einer Datei (im json Format) zur Verfugung.

Im Grund muss ich doch nur drei Input Daten (a,n,m) in die json Datei eintragen. Wie mache ich das und wie lese ich das aus und implementiere das ins Programm?
BlackJack

@loyloep: Du solltest mal aufräumen und nicht benutzte Importe entfernen. Sternchenimporte sollte auch nicht machen, da holt man sich alles mögliche in das Modul und überschreibt wenn man Pech hat auch eingebaute Funktionen und Datentypen.

Die Klasse ist hochgradig unsinnig → Weg damit!

Du Benutzt gar keine `Decimal`-Objekte sondern `int` und `float` also nicht das was gefordert ist und die Präzision der Rechenoperationen würdest Du in dem Code auch dann nicht variieren wenn Du `Decimal`-Objekte verwenden würdest.

Im ersten Beitrag steht noch etwas von einer rekursiven Lösung die gefordert wird, aber in keinem der Beiträge ist eine rekursive Funktion zu sehen.

Das sieht alles extrem planlos und geraten aus. So funktioniert Programmieren nicht.

Und beim JSON fragst Du schon wieder ohne irgendwie Eigeninitiative zu zeigen. Das `json`-Modul ist dokumentiert, für JSON-Format gibt es ebenfalls eine Spezifikation.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@loyloep: Wenn zu Anfang eines Studiums noch alles neu ist, sind Beispiele oft hilfreich. Vermutlich seid ihr bereits an der nächsten Übung, daher hier ein Beispiel für die Ausgabe des Divisionsergebnisses von Zahlen des Python Types "Decimal" mit zunehmender Präzision:

Code: Alles auswählen

from decimal import Decimal, getcontext

def divide_with_precision(x, y, precision):
    getcontext().prec = precision
    print Decimal(x) / Decimal(y)

for precision in range(2, 21, 2):
    divide_with_precision(1, 7, precision)

Diese Lösung erfolgt iterativ, was anhand der Aufgabenstellung naheliegend wäre. Konkret war aber eine rekursive Lösung gefragt, was dann so aussehen könnte:

Code: Alles auswählen

from decimal import Decimal, getcontext

def divide_with_precision(x, y, precision):
    getcontext().prec = precision
    print Decimal(x) / Decimal(y)
    if precision < 20:
        divide_with_precision(x, y, precision+2)
        
divide_with_precision(1, 7, 2)
Didaktisch ist die Forderung einer rekursiven Lösung sinnvoll, um ein Gefühl für diese Form von Lösungsansatz zu vermitteln.

Wie Du siehst, brauchst Du keine Integralklasse (wozu?!) und die ganzen Importe (außer Decimal und getcontext) auch nicht.

Ähnlich einfach sollt ihr vermutlich auch bei der Implementierung von "readJson" vorgehen. Hierfür brauchst Du nur zu wissen, wie eine Datei eingelesen wird. Und für das geforderte Json-Format gibt es auch Unterstützung aus der Standard-Library.
Zu einem Studium gehört auch, dass man diese Quellen sucht und liest.
Gelöscht2200

Danke für die aufschlussreiche Antwort. Angelehnt an den Beispielen habe ich nun mein Programm umprogrammiert. Nun funktioniert es aber nicht und ich verstehe nicht warum? Hat das irgendwas mit den Decimal zu tun?

Code: Alles auswählen

from __future__ import division
from decimal import Decimal, getcontext
from sympy import *

import numpy as np
import decimal
import json

        

def integral(a,n,m):              # Methode (Berechnung der Integral-Annäherungsformel)
        getcontext().prec = m     # Mantissenlänge (Präzision)
        for i in range(1,n):
                Decimal(n) = Decimal(1)
                Decimal(y) = Decimal(1)/Decimal(n) - Decimal(a) * Decimal(y)        # Integral-Annäherungsformel
                print ("y: ", y)
                if m < 20:
                        integral(a,n,m+2)

integral(10,10,20)
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@loyloep: "Funktioniert nicht" ist eine ziemlich schlechte Fehlerbeschreibung. Du bekommst einen Traceback, der sehr genau sagt, was denn da nicht stimmt. Sternchenimporte solltest Du unterlassen. Sympy importiert dir annähernd 600 Namen, darunter so schöne wie 'var', 'python', und 20 die so auch in math vorkommen.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@loyloep: Die erste Fehlermeldung dürftest Du wohl an dieser Stelle erhalten:

Code: Alles auswählen

Decimal(n) = Decimal(1)
Es ist jetzt wichtig, dass Du selbst herausfindest, was diese Fehlermeldung bedeutet und warum dieser Fehler auftritt.
BlackJack

@loyloep: Vielleicht noch als Hinweis: Python bringt eine interaktive Shell mit in der man Sachen ”live” ausprobieren kann um ein besseres Gefühl für die Datentypen, Operationen, und Ergebnisse zu bekommen.

Und Du solltest mindestens nebenher ganz normal Python lernen ohne speziellen Fokus auf Dein konkretes zu lösendes Problem. In der Uni wird üblicherweise erwartet das man sich in so etwas wie Programmiersprachen selbstständig einarbeitet und nicht darauf baut das alles in den Veranstaltungen oder Tutorien ”vorgeturnt” wird. Der Fehler den kbr herausgestellt hat ist nämlich nicht speziell mit der Aufgabe verknüpft, sondern offenbart ein ganz grundsätzliches Fehlverständnis von Python-Syntax/-Semantik. Was denkst Du denn was diese Zeile bewirken soll? Also was sind die Zwischenergebnisse der einzelnen Teilausdrücke auf beiden Seiten der Zuweisung und woher weisst Du wo Ausrücke stehen dürfen und wo nicht?
Gelöscht2200

Der Fehler taucht in der Zeile 19

Code: Alles auswählen

Decimal(n) += Decimal(1)
auf mit der Beschreibung: Syntax-Fehler: can't assign function call.

Was hier in dieser Zeile passieren soll ist, dass die Variablen n plus Eins addiert werden soll, und dass nicht in floating point sondern in Decimal.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@loyloep: BlackJack hat Dich schon darauf hingewiesen, dass Python einen interaktiven Interpreter mitbringt, in dem Du experimentieren kannst. Ich habe hier mal ipython genommen, aber das macht keinen Unterschied:

Code: Alles auswählen

In [1]: from decimal import Decimal

In [2]: i = Decimal(1)

In [3]: i
Out[3]: Decimal('1')

In [4]: i += 2

In [5]: i
Out[5]: Decimal('3')
Der interaktive Interpreter ist gerade für Anfänger eine tolle Sache. Gebrauche ihn.
Gelöscht2200

Ich habe den Fehler gefunden. Da es erneut zu einer Fehlermeldung gekommen ist, nehme ich doch wieder mein anfängliches Programm. Es mag komplizierter und mit viel unnützen Zeug beladen sein. Das ist mir aber egal. Denn es läuft nun auch mit Decimal-Darstellung. Nur die Implementierung einer If-Schleife in der die Variable M für die Mantissenlänge variert wird funktioniert nicht.

Code: Alles auswählen

from __future__ import division
from sympy import *

import numpy as np
import decimal


ctx = decimal.getcontext()


class Integral(object):    # Klasse, deren Objekte Skalare sind 

        def __init__(self, a, n, m):           # Konstruktor
                self.Variable = a  
                self.Wiederholung = n 
                self.Mantisse = m
        

        def integral(self,a,n,m):              # Methode (Berechnung der Integral-Annäherungsformel)
                D = decimal.Decimal            # Decimal -Darstellung von Zahlen
                ctx.prec=m                     # Mantissenlänge
                y =  D("0")
                for i in range(1,n):
                        n += D("1")
                        y = D("1")/D(n) - D(a) * D(y)        # Integral-Annäherungsformel
                        print ("y: ", y)
                


objekt = Integral(10,10,6)      # Klasse aufrufen mit Variablen, a,n,m

objekt.integral(10,10,6)        # Methode aufrufen mit Variablen a,n,m

BlackJack

@loyloep: Das sollte Dir nicht egal sein, denn ganz ehrlich wenn Du so etwas zeigst und nach Hinweisen nicht überarbeiten willst, dann dürfte über kurz oder lang jedem potentiellen Helfer hier Dein Problem egal sein.

Demjenigen der das bewerten wird, dürfte der Unsinn auch nicht egal sein. Lösungen sollten schon so aussehen als wenn man verstanden hätte was man da macht und man nicht wild herumgeraten hat. Für die unsinnige Klasse und die unnötigen Importe würde ich Punktabzug geben. Und das die Mantisse nicht variiert wird, gibt ganz sicher Punktabzug, denn die Aufgabe wird da ja nicht so gelöst wie sie soll. Rekursion fehlt auch. Also letztendlich weiss ich gar nicht worauf man da überhaupt Punkte geben soll.
Antworten