- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 21

Thema: Rechnen mit Gleitkommazahlen

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    15.01.2008
    Ort
    Siegen, Germany, Germany
    Beiträge
    441

    Rechnen mit Gleitkommazahlen

    Hallo zusammen,

    ich habe einen Integer Wert, der den Bereich -255 bis 255 abdecken sollte. Der Wert soll sich aus folgender Rechnung ergeben:

    (100/65536)* wert * 100;

    Nun wird da ja eine Zahl raus kommen, die nicht in ein Integer passt, ich bin davon ausgegangen, dass die Nachkommastellen einfach weggelassen werden. Es kommt aber immer 0 raus?
    liebe Grüße
    Der Daniel
    -
    Meine Projektseite:
    http://projects.weber-itam.de

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    05.03.2011
    Ort
    Graz
    Beiträge
    29
    Probier mal Wert*10000/65536, das ist rundungstechnisch auf jeden Fall besser.
    Ohne Code ist es schwierig was zu sagen, aber bist du dir sicher, dass der Compiler bei der Rechnung auch intern Floats benutzt? Ich mir nämlich nicht

    mfg

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    41
    Beiträge
    1.780
    Die Division durch 65536 ist das Problem, denn der Compiler interpretiert alle Werte als Integer (es sei denn, wert ist ein float).

    Eine mögliche Lösung sähe so aus:
    Code:
    (int)((100.0f / 65536.0f) * (float)wert * 100.0f);
    oder
    (int)(((float)100 / (float)65536) * (float)wert * (float)100);
    Es gibt aber auch noch eine etwas elegantere Lösung, wenn man die Reihenfolge geringfügig ändert:
    Code:
    (100 * 100 * wert) >> 16;
    bzw.
    (10000 * wert) >> 16;
    Hier habe ich die rechenintensive Division durch einen einfachen Rechtsshift ersetzt, der wesentlich schneller ist (geht immer, wenn man durch 2^n dividieren möchte). Wichtig dabei ist aber, daß die Multiplikation vorher erfolgt, denn sonst entsteht wieder das selbe Problem wie bei deiner Variante.
    So viele Treppen und so wenig Zeit!

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Zitat Zitat von Felix G Beitrag anzeigen
    Code:
    (10000 * wert) >> 16;
    Hier habe ich die rechenintensive Division durch einen einfachen Rechtsshift ersetzt, der wesentlich schneller ist (geht immer, wenn man durch 2^n dividieren möchte). Wichtig dabei ist aber, daß die Multiplikation vorher erfolgt, denn sonst entsteht wieder das selbe Problem wie bei deiner Variante.
    ACHTUNG: Bei vorzeichenbehafteten Zahlen funktioniert der Rechtsshift nur in bestimmten Situationen (Vielfache von , da er NICHT zur Null hin rundet. Beispiel (für 3-Bit-Integer):
    Code:
    -1 >> 1 = -1 // Falsch
    -2 >> 1 = -1
    -3 >> 1 = -2 // Falsch
    -4 >> 1 = -2
    Allerdings kann man den entstehenden Fehler auch ausbügeln (in diesem Beispiel durch eine Addition von 1)

    mfG
    Markus

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von Felix G Beitrag anzeigen
    Es gibt aber auch noch eine etwas elegantere Lösung, wenn man die Reihenfolge geringfügig ändert:
    Code:
    (100 * 100 * wert) >> 16;
    bzw.
    (10000 * wert) >> 16;
    Hier habe ich die rechenintensive Division durch einen einfachen Rechtsshift ersetzt, der wesentlich schneller ist (geht immer, wenn man durch 2^n dividieren möchte).
    Dieser Unsinn ist wohl auch einfach nicht totzukriegen.

    Eine solche Simpelst-Optimierung macht natürlich auch der Compiler selber. Du gewinnst mit dieser Schreibweise also rein gar nichts. Du verlierst nur etwas, nämlich die Offensichtlichkeit der eigentlichen Absicht hinter dem Code.

    Also: wenn du eigentlich dividieren willst, dann benutze '/', und wenn du schieben willst, dann benutze '>>'. Das Eine durch das Andere zu ersetzen, weil es schneller ist (es gibt übrigens auch Prozessoren, wo die Division schneller ist), kannst du getrost dem Compiler überlassen.
    MfG
    Stefan

  6. #6
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    08.04.2009
    Ort
    an der Ostsee
    Beiträge
    334
    moin moin,

    warum so viel Aufwand?
    (100/65536)* wert * 100 -->> das ist doch 1Byte * ~1,52...

    Ich würde da eine kleine Tabelle nehmen, es sind 256 Werte zu 16Bit notwendig.

    so:
    ausWert = Tabelle[abs(einWert)]
    if Signum(einWert) then ausWert = - ausWert


    Warum soll da überhaupt was umgerechnet werden, was ist der Hintergrunf?

    Mit Gruß
    Peter

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    36
    Beiträge
    1.225
    Zitat Zitat von Peter1060 Beitrag anzeigen
    Ich würde da eine kleine Tabelle nehmen, es sind 256 Werte zu 16Bit notwendig.
    Eieiei, warum nicht gleich ein Koprozessor? Oder halt, noch besser: Wir rüsten gleich auf einen ARM der neuesten Generation um ... oder vielleicht nicht doch einen Intel Core iSonstwas Extreme?

    Eine kleine 32-Bit Multiplikation (wert * 10000) mit nachfolgender Division/Wegwerfen der letzten zwei Bytes schafft der AVR auch noch ohne Lookup-Table oder sonstige Geschütze die hier aufgefahren werden. Vielleicht nicht schneller, aber vermutlich Platzsparender als eine Lookup-Table mit 2^12 Einträgen. (Ergibt sich, wenn du ausrechnest, in welchem Wertebereich "wert" liegen kann, damit sich nach der genannten Formel Werte von +-255 ergeben)

    mfG
    Markus

  8. #8
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    08.04.2009
    Ort
    an der Ostsee
    Beiträge
    334
    >>2^12 Einträgen
    das ist doch Unfug, wenn 2^8.

    ...die Tabelle sind 512 Bytes plus Prog zum auslesen.
    Der TO keinen Prof. oder Sprache angegeben hat, kann keiner sagen, wieviel Speicher notwendig ist.

    Da ich in 8051 Assembler arbeite, könnte ich den genauen Bedarf für diese Sache ermitteln.

    Mit Gruß
    Peter

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von Felix G
    Registriert seit
    29.06.2004
    Ort
    49°32'N 8°40'E
    Alter
    41
    Beiträge
    1.780
    Zitat Zitat von sternst Beitrag anzeigen
    Eine solche Simpelst-Optimierung macht natürlich auch der Compiler selber. Du gewinnst mit dieser Schreibweise also rein gar nichts. Du verlierst nur etwas, nämlich die Offensichtlichkeit der eigentlichen Absicht hinter dem Code.
    Zugegeben, bei konstantem Divisor gewinnt man üblicherweise nichts. Ist der Divisor aber nicht konstant, kann man Divisionen deutlich beschleunigen indem man sie in eine Multiplikation und einen Rechtsshift umbaut (denn das kann der Compiler selbst nicht mehr optimieren).

    Daß das nur für Controller gilt die keinen schnellen Hardware Dividierer haben, versteht sich wohl von selbst.
    So viele Treppen und so wenig Zeit!

  10. #10
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von Felix G Beitrag anzeigen
    Ist der Divisor aber nicht konstant, kann man Divisionen deutlich beschleunigen indem man sie in eine Multiplikation und einen Rechtsshift umbaut (denn das kann der Compiler selbst nicht mehr optimieren).
    Und haben wir hier einen solchen Fall? Nein, es geht ganz konkret um eine Division durch 65536. Und du empfiehlst, dass durch ">> 16" zu ersetzen, weil es "eleganter" und "schneller" wäre. Sorry, aber das ist eben ziemlicher Unsinn.

    Und so nebenbei: Zeig mal, wie du das mit einem nicht konstanten (und damit unbekannten) Divisor machst. Was du wohl eher meinst, ist ein konstanter Divisor, der aber keine 2er-Potenz ist.
    MfG
    Stefan

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Zinsaufgabe rechnen (mit dem Boe-Bot)
    Von butt-bot im Forum Software, Algorithmen und KI
    Antworten: 4
    Letzter Beitrag: 28.03.2007, 21:14
  2. Gruppenschaltung rechnen
    Von Larzarus im Forum Elektronik
    Antworten: 7
    Letzter Beitrag: 28.07.2006, 16:55
  3. Rechnen mit Bascom
    Von atvler im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 12
    Letzter Beitrag: 22.05.2006, 21:50
  4. Rechnen mit 3 Registern
    Von Philipp83 im Forum Software, Algorithmen und KI
    Antworten: 9
    Letzter Beitrag: 10.05.2006, 10:46
  5. Rechnen mit Gleitkommazahlen in Bascom
    Von Stefan im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 10.03.2004, 20:39

Berechtigungen

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

12V Akku bauen