-         

Ergebnis 1 bis 10 von 10

Thema: Rechnen mit double-Variablen

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270

    Rechnen mit double-Variablen

    Anzeige

    Hallo Leute,

    ich kämpfe hier momentan an einer Rechnung in Bascom und komm einfach nimmer weiter.

    Also zunächst mal der Sub um den es geht:

    Code:
    Sub Refresh_koordinaten
       Toggle Error_led
       Statusbit.calc_koordinaten = 0
    
       X = Links / 12.143
       Y = Rechts / 12.143
    
       Cls
       Locate 1 , 1
       Lcd str(x)
    
       Locate 2 , 1
       Lcd str(y)
    
    Return
    End Sub
    Die Variablen sind wie folgt deklariert:
    x as double
    y as double
    links as byte
    rechts as byte

    Anhand der LED sehe ich, das der Sub desinitif immer genau dann aufgerufen wird, wenn ich das möchte.

    Allerdings wird mir dann auf dem Display auf beiden Zeilen immer nur eine 0 angezeigt.
    Wenn ich mir variablen "links" und "rechts" anzeigen lasse, dann haben die immer einen Wert zwischen 0 und 20. (Eine von beiden hat immer !00%ig genau 20, denn genau dann wird das Sub aufgerufen, die andere Variable ist dann <=20)

    Nun hab ich schon etwas rum brobiert und mit die Variablen x und y runden lassen, in eine Byte-Varaible schreiben lassen und dann das Byte anzeigen lassen. Als ergebnis gabs aber auch hier immer 0
    Auch eine Formatierung durch int(x) und int(y) brachte keine Veränderung: nach wie vor 0

    Ich muss dazu sagen, das es das erste mal ist, das ich in Bascom mit double-Variablen arbeite.
    Kann mir jemand sagen was ich falsch mache?

    Gruß Robodriver
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  2. #2
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.836
    Versuch mal
    $swstack=
    $framesize=
    zu erhöhen.
    http://www.roboternetz.de/wissen/ind.../Bascom_Inside
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    25.10.2007
    Ort
    41462 Neuss
    Alter
    49
    Beiträge
    375
    - das hilft jetzt zwar nicht weiter, aber auch wenn die sprache keinen unterschied zwischen groß und klein macht, sollte man nicht für ein und dieselbe sache verschiedene schreibweisen verwenden. das ist schlechter stil und für andere schwer zu lesen. so was sollte man sich erst gar nicht angewöhnen, und sei es auch nur, weil es zwangsläufig zu fehlern führt, wenn du später mal mit einer programmiersprache arbeitest, die zwischen groß und klein unterscheidet!

    - warum double und nicht single ?

    - du gehst davon aus, das der fehler in der sub liegt, dass muss aber nicht sein. besser auch den code drumrum posten. das erhöht die chancen, das ein fehler gefunden wird.

    - nur zum test würd ich mal die (beiden) operanten der division vorher explizit in double wandeln lassen und dann erst die division durchführen.

    -multiplizier mal x und y nach der division wieder mit 12.143, konvertier es in byte und lass es anzeigen. kommen jetzt wieder werte zwischen 0 und 20 ?

  4. #4
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270
    Also danke erstmal für die Antworten

    @PicNick:
    hwstack ist schon bei 64
    swstack bei 32

    habs mal auf hwstack=128 und swstack=32 erhöht
    Das Ergebnis bleibt bei null

    @fumir:
    1.: was meinst du mit groß/klein schreibung? Weil das x und y in den klammern klein ist und weiter oben groß geschrieben?
    Da muss ich dich enttäuschen. Aber das geht bei Bascom nicht anders.
    Wenn ich variablen klein schreibe, dann ändert Bascom den ersten Buchstabe IMMER AUTOMATISCH auf große Schreibweise.
    Wenn ich aber hingegen bei dem str() das x groß schreibe, dann wird es AUTOMATISCH auf ein kleines x umgeschrieben. Da kann man absolut nichts gegen machen. Sobald der Cursor die Zeile verlässt, wird es vom Compiler geändert.
    2.: double habe ich gewählt, weil ich eine größtmögliche Genauigkeit erreichen muss. Denn kleinste Fehler addieren sich hier auf und bewirken dann größeres nach 1000 Rechnungen.
    3.: Ich habe absichtlich nicht das komplette Programm gepostet, denn es umfasst 829 Programmzeilen (22kB Hex-File). Ich denke das wird sich hier keiner Durchlesen. Und ich wüsste jetzt auch nicht weswegen der restliche Programmcode hier stören sollte. Denn die Variablen x und y gibt es ausschließlich in diesem Sub. sie existieren an keiner anderen Stelle im Code. Die Variablen "links" und "rechts" existieren an zwei anderen stelle nochmal und das sind 2 Interrupts. Die schaun wie folgt aus:
    Code:
    Overflow_links:
    Links = 20
    Rechts = Enc_rechts - 236                                   ' - 243
    Load Timer0 , 20
    Load Timer1 , 20
    Statusbit.calc_koordinaten = 1
    Return
    
    Overflow_rechts:
    Rechts = 20
    Links = Enc_links - 236                                     ' - 256-20
    Load Timer0 , 20
    Load Timer1 , 20
    Statusbit.calc_koordinaten = 1
    Return
    Dieser Interrupt wird bei einem Timer Overflow aufgerufen. Der Timer ist als Counter konfiguriert. Es kommt also alle 20 Takte zu einem Interrupt. Momentan zum Testen wird der Interrupt nur einmal aufgerufen (Ich gebe einfach 23 Takte auf den einen Counter.

    4.: Habe die Berechnung jetzt mal wie folgt umgeschrieben:
    Code:
       X = Links
       Y = Rechts
    
       X = X / 12.143
       Y = Y / 12.143
    Auch dabei kommt für x und y Null heraus

    5.:
    Wenn ich es so schreibe:
    Code:
       X = Links
       Y = Rechts
    
       X = X / 12.143
       Y = Y / 12.143
    
       X = X * 12.143
       Y = Y * 12.143
    Dann kommt für x und y auch Null heraus. Das verstehe ich nicht

    Hab jetzt aber doch mal versucht x und y als Single zu deklarieren (In dem Code den ich im ersten Post geschickt hatte).
    Und siehe da: Es funktioniert einwandfrei.
    Aber warum nicht mit Double? Das verstehe ich nicht


    PS: Ich schreib mal noch dazu das ich einen ATMega 32 verwende. Das hatt ich noch vergessen...
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Zitat Zitat von robodriver
    Da muss ich dich enttäuschen. Aber das geht bei Bascom nicht anders.
    Wenn ich variablen klein schreibe, dann ändert Bascom den ersten Buchstabe IMMER AUTOMATISCH auf große Schreibweise.
    Wenn ich aber hingegen bei dem str() das x groß schreibe, dann wird es AUTOMATISCH auf ein kleines x umgeschrieben. Da kann man absolut nichts gegen machen. Sobald der Cursor die Zeile verlässt, wird es vom Compiler geändert.
    Das kannst du schon verhindern. Schau mal unter
    Options -> Environment -> Editor -> Don't change case.

    Ich kann dein Problem bei mir auch sehen. Ist also vollkommen unabhängig vom drumherum. Im Simulator sieht man gut was passiert.
    Wenn ich die Variablen Links und Rechts zuerst in eine Single Variable schiebe und dann diese durch 12.143 teile und in X speichere, dann funktioniert es. Vielleicht als workaround.

    Zitat Zitat von fumir
    - nur zum test würd ich mal die (beiden) operanten der division vorher explizit in double wandeln lassen und dann erst die division durchführen.
    Wie soll das gehen?

    Gruß

    Rolf

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    25.10.2007
    Ort
    41462 Neuss
    Alter
    49
    Beiträge
    375
    @robodriver
    zu 1: so was hätte ich nie für möglich gehalten, aber man lernt eben nie aus zum glück kann man es wohl abschalten, wie for_ro schreibt.

    zu2: wenn x und y wirklich nur in der sub stehen, dann sollte single aber reichen: wenn man ne zahl zwischen 0 und 20 durch ne 5 stellige dezimalzahl dividiert, dann kann das ergebnis auch nur ne genauigkeit von etwa 5 bis 6 stellen haben, oder? wie auch immer, es spricht ja auser speicherplatz und rechengeschwindigkeit erst mal nix gegen die verwendung von double.

    zu3: naja, das ist eher ein genereller tip. es ist einfach kontraproduktiv jemanden der nen fehler suchen soll von anfang an in ne bestimmte richtung zu lenken. in dem fall ists ja prima, wenn die variablen sonst nirgens auftauchen. aber das haben schon viele leute geglaubt, bis sie später irgendwo nen tipfehler in ihrem programm gefunden haben
    auserdem sieht die sub ja eigentlich ganz ok aus, da liegts nahe nach irgendwelchen unerwünschten seiteneffekten zu suchen.

    zu4: ja, so meinte ich das. aber ich hätte die konstante auch noch vorher in ne double variable gespeichert.

    zu5: na dann weist du jetzt schon mal, das bereits die berechnung fehlschlägt und das problem nicht erst beim umwandeln in den string bzw. die übergabe an lcd stattfindet!
    ich hätte zwar jetzt nicht vermutet, das es mit single besser geht als mit double, aber es wundert mich auch nicht. möglicherweise wandelt Bascom die konstante in nen single und bekommt dann probleme weil die division zwischen verschiedenen typen stattfindet. Bascom ist eben nicht vergleichbar mit nem compiler wie gcc. da gibt es immer die möglichkeit, das der compiler nen fehler hat (oder so schlecht dokumentiert ist, das es zu mißverständnissen kommt) ich hab z.b. in der Bascom doku gelesen, das operanten einer arithm. operation immer gleichen typ haben müssen. an anderer stelle steht, das die operation immer im typ des ergebnisses ausgeführt wird. das widerspricht sich teilweise bzw. ist unklar formuliert. dazu kommt, dass double wohl eher selten verwendet wird, und deshalb compilerfehler in dem zusammenhang nicht so schnell gefunden werden.

    @for_ro
    na einfach beide operanten erst mal einzeln ner double variable zuweisen und dann die division mit den double variablen durchführen.

    ich hab mal lange in nem c/c++ programm nach nem fehler gesucht, bis mir klar wurde, das eine konstante (in nem #define) eben nicht wie ich dachte in ne 64bit integer sondern nur in ne 32bit integer umgewandelt wurde. deshalb sollte man eben #define vermeiden (keine typprüfung) aber das ist jetzt ein anderes thema.

  7. #7
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    28.05.2007
    Ort
    Mannheim
    Alter
    30
    Beiträge
    270
    Okay, das heißt also das hier scheinbar ein Compiler-Fehler vor liegt?

    Habs mir aber nochmal durchgerechnet. Vielleicht komm ich mit Single auch hin. Die umrechnung /12.143 ist die Umrechnung von Incrementen in cm. Wenn dieses Ergebnis auf 6 Stellen nach dem Komma genau ist, dann habe ich bei 10Metern eine Fehlergenauigkeit von 0,001 cm (0,01mm).
    Ich denke damit kann man leben.
    Die Ganzen Daten sind dann zur Berechnung von Winkel und Position in einem Koorinatensystem. Dazu die hohe Genauigkeit


    @fumir:
    Naja, ich habs ja auch mal versucht vorher die Variablem links und rechts in eine Double-Variable zu schreiben und dann die Division durch zu führen:
    Code:
       X = Links 
       Y = Rechts 
    
       X = X / 12.143 
       Y = Y / 12.143
    x und y sind ja als Double deklariert.
    Also wäre diese Rechnung im Ergebnis und von den Werten her Double.
    Was aber vielleicht noch sein könnte, das er mit der 12.143 nicht so ganz klar kommt... vielleicht sollte man die vorher erst noch in eine extra Variable bzw. Constante schreiben.
    Wer aufhört besser zu werden, hat aufgehört gut zu sein

    Jeder I/O Port kennt drei Zustände: Input, Output, Kaputt

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    02.09.2005
    Ort
    Greifswald
    Beiträge
    17
    Hallo,

    mein Eindruck ist, dass Double nur mit Double rechnen kann.
    Habe aber nur eine Demo Version.
    Das folgende Beispiel im Einzelschritt im Simulator ausführen
    und dabei die Variablen anzeigen lassen.
    Dazu sollte man sich die Hilfe zu Double ansehen.

    Gruß Manfred


    Code:
    'BASCOM-AVR 1.11.8.7  DEMO Edition
    
    $regfile = "m32def.dat"
    $crystal = 1000000
    $hwstack = 64
    $swstack = 8
    $framesize = 24
    
    Dim X As Double
    Dim Y As Double
    Dim Z As Double
    
    Dim Rechts As Double
    Dim Links As Byte
    
    Dim Help1 As Long
    Dim Help2 As Double
    
    Links = 20
    Rechts = 20
    
    X = Links / 12.143
    Y = Rechts / 12.143
    
    Help1 = Links                 'Byte --> Long
    Help2 = Help1                 'Long --> Double
    Z = Help2 / 12.143
    
    End

  9. #9
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.112
    Zitat Zitat von mlgahoc
    mein Eindruck ist, dass Double nur mit Double rechnen kann.
    Wie schon oben geschrieben funktioniert double mit single auch. Da sind halt floating point unter sich.
    Byte und Integer geht nur nach single, der Zwischenschritt muss wohl sein.

    Gruß

    Rolf

  10. #10
    Neuer Benutzer
    Registriert seit
    17.02.2010
    Ort
    Augsburg
    Beiträge
    1
    Hallo,
    die Einträge sind schon etwas älter, allerdings haben immer noch einige die gleichen Problem. So wie ich diese Woche

    Letztendlich habe ich herausgefunden, dass Double nicht mit Byte rechnen kann! Auch nicht umwandeln.

    Wenn man also ein Register (wie Counter1) oder eine Byte-Variable in die Berechnung einbeziehen will, muß man sie zuerst in Long überführen.

    Dann läuft Double prima und schön genau.

    Vielleicht hilft es jemandem, der auf der Suche ist

    Grüße
    Testus


    hier ein Schnipsel, Temp ist eine Long :

    N_base_float = 73.0
    Temp = Capture1
    Temp_float = Temp
    N_base_float = N_base_float + Temp_float
    Temp = Tim1_16
    Temp_float = Temp
    Temp_float = 65536.0 * Temp_float

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •