Runden + Hochzählen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
stoffl6781
User
Beiträge: 11
Registriert: Sonntag 14. Dezember 2014, 19:04

Hallo zusammen,

ich habe einen Script mit einem Counter - mehrere Buttens die einen wert addieren oder subtrahieren.
Nun ist mir aufgefallen, wenn ich öfters auf +0.1 Drücke dann kommt als Ergebnis 0,89999
Stimmt nicht - sollte 0,90 da setehen ...

Nun dachte ich ich kann das mit round(,2) in den Griff bekommen ... leider ohne Erfolg ...

Siehe:

Code: Alles auswählen

    def increase(self):
            zehner=0.1
            roundzehner=round(zehner,1)
            self.value += roundzehner
Wo ist mein Denkfehler?

danke für euere Hilfe!

Code: Alles auswählen

import tkinter as tk
class Counter(object):
    def __init__(self, start_value=0.0):
            self.value = start_value
            
    def increase(self):
            zehner=0.1
            roundzehner=round(zehner,1)
            self.value += roundzehner
       
    def increase1(self):
            self.value += 1.00

    def increase10(self):
            self.value += 10.00

    def decrease(self):
            self.value -= 0.1
       
    def decrease1(self):
            self.value -= 1

    def decrease10(self):
            self.value -= 10
     
class CounterUI(tk.Frame):
    def __init__(self, master, counter):
        tk.Frame.__init__(self, master)
        # Counter plus
        self.counter = counter
        tk.Button(self, text='+0,1', command=self.increase).pack()
        tk.Button(self, text='+1  ', command=self.increase1).pack()
        tk.Button(self, text='+10 ', command=self.increase10).pack()
        #Ausgabe counter
        self.counter_label = tk.Label(self, text=self.counter.value)
        self.counter_label.pack()
        #Counter minus
        tk.Button(self, text='-10 ', command=self.decrease10).pack()
        tk.Button(self, text='-1  ', command=self.decrease1).pack()
        tk.Button(self, text='-0,1', command=self.decrease).pack()
        tk.Button(self, text='End ', command=self.master.destroy).pack()

       
    def increase(self):
        self.counter.increase()
        self.counter_label['text'] = self.counter.value

    def increase1(self):
        self.counter.increase1()
        self.counter_label['text'] = self.counter.value

    def increase10(self):
        self.counter.increase10()
        self.counter_label['text'] = self.counter.value
     
    def decrease(self):
        self.counter.decrease()
        self.counter_label['text'] = self.counter.value
    def decrease1(self):
        self.counter.decrease1()
        self.counter_label['text'] = self.counter.value

    def decrease10(self):
        self.counter.decrease10()
        self.counter_label['text'] = self.counter.value
     
     
def main():
    root = tk.Tk()
    ui = CounterUI(root, Counter())
    ui.pack()
    root.mainloop()
     
if __name__ == '__main__':
    main()
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Überraschung:

Code: Alles auswählen

>>> .1 + .2
0.30000000000000004
Guckstu hier:
http://floating-point-gui.de/
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@stoffl6781: Diese ganzen `increase`- und `decrease`-Methoden sind ein bisschen zuviel des guten. Wenn man weiss welche der Methoden man aufrufen muss, könnte man auch *eine* allgemeine Methode aufrufen die man beispielsweise `change()` nennt und der man den Betrag der Änderung als Argument übergibt. Es passiert doch in jeder dieser Methoden das selbe, nur der Wert unterscheidet sich.
stoffl6781
User
Beiträge: 11
Registriert: Sonntag 14. Dezember 2014, 19:04

pillmuncher hat geschrieben:Überraschung:

Code: Alles auswählen

>>> .1 + .2
0.30000000000000004
Guckstu hier:
http://floating-point-gui.de/
HI, danke für die info - wie kann ich das in ordnung bringen? - sprich dass nur auf 2 NK gerechnet werden?

habe schon versucht:

Code: Alles auswählen

        #Ausgabe counter
        OutLabel1 = self.counter_label = tk.Label(self, height=butheight, width=butwidth, font=("Arial",15), fg="white", bg="darkred", text=str(round(self.counter.value(), 2)) + " °C")
        OutLabel1.grid(row=0, column=4)
Allerdings mit Fehler:
Type Error 'float' object is tnot callabel


Anbei der Komplette Sricpt. Bitte nicht erschrecken ich versuche von einem Vordefinierten Script Temperaturfühler auszulesen und ich bin auf dem Holzweg. Werde mir dringend das mit den Klassen nochmals erklären lassen müssen - versehe es leider nur so lala ... =(

Code: Alles auswählen


import tkinter as tk
from tkinter import *
from time import sleep
from temperature import TempDevices

class Counter(object):
    def __init__(self, start_value=0.0):
            self.value = start_value
            
    def increase(self):
            self.value +=0.10
       
    def increase1(self):
            self.value += 1.00

    def increase10(self):
            self.value += 10.00

    def decrease(self):
            self.value -= 0.1
       
    def decrease1(self):
            self.value -= 1

    def decrease10(self):
            self.value -= 10
            
             
class CounterUI(tk.Frame):
    def __init__(self, master, counter):
        tk.Frame.__init__(self, master)
        
        # Buttons Style
        self.counter = counter
        bgbut="gray6"
        bgbutactbackgd="gold2"
        bgbutactforegd="gold2"
        bgbutborder=2
        bgbutfont="Arial", 15
        bgbutfg="gold2"
        butheight=3
        butwidth=5
        
        # Label mit aktuellen Temperaturen in Grid
#        self.tempLabels = self.Thermometer(self.master, t)
#        for t in self.tempLabels: t.pack()
        
#        self.TempLabels = [Thermometer(self.master)]
#        for t in self.tempLabels
#        self.TempLabels.grid(row=0, column=0)
        #Counter plus
        IncButton1 = tk.Button(self, height=butheight, width=butwidth, text="+0,1", font=bgbutfont, fg= bgbutfg, bg=bgbut, bd=bgbutborder, activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.increase)
        IncButton1.grid(row=0, column=1)

        IncButton2 = tk.Button(self, height=butheight, width=butwidth, text="+1", font=bgbutfont, fg= bgbutfg, bg=bgbut, bd=bgbutborder, activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.increase1)
        IncButton2.grid(row=0, column=2)

        IncButton3 = tk.Button(self, height=butheight, width=butwidth, text="+10", font=bgbutfont, fg= bgbutfg, bg=bgbut, bd=bgbutborder, activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.increase10)
        IncButton3.grid(row=0, column=3)
        
        #Ausgabe counter
        OutLabel1 = self.counter_label = tk.Label(self, height=butheight, width=butwidth, font=("Arial",15), fg="white", bg="darkred", text=str(round(self.counter.value(), 2)) + " °C")
        OutLabel1.grid(row=0, column=4)
        
        #Counter minus
        DecButton1 = tk.Button(self, height=butheight, width=butwidth, text='-10 ', font=bgbutfont, fg= bgbutfg, bg=bgbut, bd=bgbutborder, activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.decrease10)
        DecButton1.grid(row=0, column=5)
        
        DecButton2 = tk.Button(self, height=butheight, width=butwidth, text='-1  ', font=bgbutfont, fg= bgbutfg, bg=bgbut, bd=bgbutborder, activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.decrease1)
        DecButton2.grid(row=0, column=6)
        
        DecButton3 = tk.Button(self, height=butheight, width=butwidth, text='-0,1', font=bgbutfont, fg= bgbutfg, bg=bgbut, bd=bgbutborder, activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.decrease)
        DecButton3.grid(row=0, column=7)
        
        # Alarm Button
        self.AlarmButton1 = tk.Button(self, height=butheight, width=10, text='Alarm schalten', font=("Arial",15), fg= bgbutfg, bg="darkred", activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.convert0)
        self.AlarmButton1.grid(row=0, column=8)

        # End Button
        EndButton1 = tk.Button(self, height=butheight, width=butwidth, text='Ende', font=("Arial",15), fg="white", bg="darkred", command=self.master.destroy)
        EndButton1.grid(row=5, column=8)

    def increase(self):
        self.counter.increase()
        self.counter_label['text'] = self.counter.value

    def increase1(self):
        self.counter.increase1()
        self.counter_label['text'] = self.counter.value

    def increase10(self):
        self.counter.increase10()
        self.counter_label['text'] = self.counter.value
     
    def decrease(self):
        self.counter.decrease()
        self.counter_label['text'] = self.counter.value
    
    def decrease1(self):
        self.counter.decrease1()
        self.counter_label['text'] = self.counter.value

    def decrease10(self):
        self.counter.decrease10()
        self.counter_label['text'] = self.counter.value
        
    # Alarm Button switcher
    def convert0(self, tog=[0]):
        tog[0] = not tog[0]

        if tog[0]:
             self.AlarmButton1.config(text=self.counter.value, font=("Arial",15), fg="white")
        else:
             self.AlarmButton1.config(text='Alarm Aus', font=("Arial",15), fg="white")
        
class Thermometer(Label):
    def update(self):
        text = str(round(self.device.read(), 2)) + " °C"
        self.config(text=text)
        self.master.after(500, self.update)

    def __init__(self, master, tempDevice):
        Label.__init__(self, font=("Arial", 20))
        self.master = master
        self.device = tempDevice
        self.update()
  
def main():
    root = tk.Tk()
    master = root
    root.title('RPICTRL')
    root.geometry("800x480")
    root.configure(background = "blue2")

    ui = CounterUI(root, Counter())
    ui.pack()
    root.mainloop()
     
if __name__ == '__main__':
    main()
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

stoffl6781 hat geschrieben:HI, danke für die info - wie kann ich das in ordnung bringen? - sprich dass nur auf 2 NK gerechnet werden?
Entweder bist du dem Link erst gar nicht gefolgt oder du bist ihm gefolgt und hast die angebotenen Informationen nicht gelesen und/oder verstanden.

Mit floats kannst du einfach nicht auf 2 Nachkommastellen rechnen. Du kannst aber bei der Ausgabe durch Formatierungsangaben eine entsprechende Anzeige erreichen. Alternativ könntest du statt Fließkommawerten auch den Datentyp Decimal verwenden.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@stoffl6781: man rechnet gar nicht auf irgendwelche Nachkommastellen, sondern formatiert die Ausgabe:

Code: Alles auswählen

text = "{0:.2f} °C".format(value)
Ich dachte ja erst, das mit dem Counter wäre nur so eine Spielerei, aber Du scheinst das ja wirklich ernsthaft einsetzen zu wollen, wobei das ja kein Counter sondern ein Temperaturregler ist. Am besten ersetzt Du den ganzen Counter-Kram durch eine einfache Zahl und die increasen und decreasen durch eine allgemeine Methode:

Code: Alles auswählen

def change_alarm_temperature(self, amount):
    self.alarm_temperature += amount
    self.counter_label['text'] = "{0:.2f} °C".format(self.alarm_temperature)
und die entsprechenden Verknüpfungen durch «command=partial(self.change_alarm_temperature, -0.1)» etc. mit partial aus functools.
stoffl6781
User
Beiträge: 11
Registriert: Sonntag 14. Dezember 2014, 19:04

Sirius3 hat geschrieben:@stoffl6781: man rechnet gar nicht auf irgendwelche Nachkommastellen, sondern formatiert die Ausgabe:

Code: Alles auswählen

text = "{0:.2f} °C".format(value)
Ich dachte ja erst, das mit dem Counter wäre nur so eine Spielerei, aber Du scheinst das ja wirklich ernsthaft einsetzen zu wollen, wobei das ja kein Counter sondern ein Temperaturregler ist. Am besten ersetzt Du den ganzen Counter-Kram durch eine einfache Zahl und die increasen und decreasen durch eine allgemeine Methode:

Code: Alles auswählen

def change_alarm_temperature(self, amount):
    self.alarm_temperature += amount
    self.counter_label['text'] = "{0:.2f} °C".format(self.alarm_temperature)
und die entsprechenden Verknüpfungen durch «command=partial(self.change_alarm_temperature, -0.1)» etc. mit partial aus functools.
Besten Dank für die Hilfe! Habe ich das so richtig verstanden?
Habe jetzt nur ein Button angepasst den rest mal gelöscht

Code: Alles auswählen


import tkinter as tk
from tkinter import *
from time import sleep
from functools import partial
#from temperature import TempDevices
             
class CounterUI(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        
        # Buttons Style
        bgbut="gray6"
        bgbutactbackgd="gold2"
        bgbutactforegd="gold2"
        bgbutborder=2
        bgbutfont="Arial", 15
        bgbutfg="gold2"
        butheight=3
        butwidth=5
        
        #Counter plus
        IncButton1 = tk.Button(self, height=butheight, width=butwidth, text="+0,1", font=bgbutfont, fg= bgbutfg, bg=bgbut, bd=bgbutborder, activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=partial(self.change_alarm_temperature, +0.1))
        IncButton1.grid(row=0, column=1)
        
        #Ausgabe counter
        OutLabel1 = self.alarm_temperature = tk.Label(self, height=butheight, width=butwidth, font=("Arial",15), fg="white", bg="darkred")
        OutLabel1.grid(row=0, column=4)
        
        
        # Alarm Button
        self.AlarmButton1 = tk.Button(self, height=butheight, width=10, text='Alarm schalten', font=("Arial",15), fg= bgbutfg, bg="darkred", activebackground=bgbutactbackgd, activeforeground=bgbutactforegd, command=self.alarm_temperature)
        self.AlarmButton1.grid(row=0, column=8)

        # End Button
        EndButton1 = tk.Button(self, height=butheight, width=butwidth, text='Ende', font=("Arial",15), fg="white", bg="darkred", command=self.master.destroy)
        EndButton1.grid(row=5, column=8)

    def change_alarm_temperature(self, amount):
        self.alarm_temperature += amount
        self.counter_label['text'] = "{0:.2f} !C".format(self.alarm_temperature)

        
    # Alarm Button switcher
    def convert0(self, tog=[0]):
        tog[0] = not tog[0]

        if tog[0]:
             self.AlarmButton1.config(text=self.counter.value, font=("Arial",15), fg="white")
        else:
             self.AlarmButton1.config(text='Alarm Aus', font=("Arial",15), fg="white")
        
  
def main():
    root = tk.Tk()
    master = root
    root.title('RPICTRL')
    root.geometry("800x480")
    root.configure(background = "blue2")

    ui = CounterUI(root)
    ui.pack()
    root.mainloop()
     
if __name__ == '__main__':
    main()
Ene Uran
User
Beiträge: 125
Registriert: Sonntag 17. September 2006, 20:14
Wohnort: Hollywood

Schau Dir mal die decimal module an.
Atomkraftwerkaktienbesitzer
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@stoffl6781: Warum ist alarm_temperature ein Label und wird beim Alarm-Knopf als command angegeben? Das macht doch so keinen Sinn. Und bevor Du jetzt wieder alle Knöpfe einzeln einbaust, denk über eine Schleife nach.
BlackJack

@stoffl6781: Der Hack bei `convert0()` mit dem veränderbaren Defaultwert ist ja extrem hässlich und vor allem total unnötig bei einer Methode. Und streng genommen auch fehlerhaft denn den Wert dort teilen sich alle Exemplare von `CounterUI`, was semantisch so sicher nicht gewollt wäre.
Antworten