Neuen Datentyp erstellen



  • Hallo,

    ich möchte gerne einen neuen Datentyp mit 17Bit anlegen der dann int17 heißen soll.

    Wie kann ich das machen? Oder geht das überhaupt?

    Ich möchte 8 Werte +/- 2π per Funk übertragen.

    Dazu ist mir folgendes durch den Kopf gegangen:
    2¹⁷=131.071 <=> -65.536...+65.535
    2π = 2*3,14159 = 6,28318
    6,28318 * 1000 ≈ 62.831 < 65.536

    Aktuell werden die Daten über float verschickt und sind damit recht groß. Bei 17Bit können somit 15 Bit je Winkel eingespart werden (8*15=120) 🤡

    Gruß Alex



  • Kannst du denn deiner API/Sendefunktion überhaupt klar machen, dass sie nur 17 Bit senden soll? 😉



  • Du kannst keinen Datentyp mit 17 Bit anlegen, du kannst lediglich eine feste Größe in Byte haben. Allerdings kannst du hier z.B. 3 Byte nehmen und davon 7 Bit wegschmeissen, bzw, wenn du mehrere davon speichern möchtest, kannst du ein Bitset verwenden.

    Beispiel:

    struct eight_17_bit_numbers
    {
        int first   : 17;
        int second  : 17;
        int third   : 17;
        int fourth  : 17;
        int fifth   : 17;
        int sixth   : 17;
        int seventh : 17;
        int eight   : 17;
    };
    

    Allerdings bezweifle ich, dass bei dir wirklich der Bedarf besteht, solche Optimierungen durchzuführen. Wozu möchtest du das tun?


  • Mod

    Wenn du so dringend Platz sparen musst (bist du sicher, dass die Not so groß ist?), dann kannst du die Daten mit Bitverschiebeoperationen in größere Datentypen einpacken. 8*17 Bit sind bei 8-Bit chars ein char[17]. Dafür muss du natürlich vorher ordentlich rechnen (Bitverschiebungen und Verundungen, dazu noch ein paar reinterpret_casts um den Compiler zu so etwas zu überreden) und verschickst dann die 17 chars und entpackst sie auf der Gegenseite wieder.

    Sei dir auch im Klaren, dass 17 Bit weniger Information enthalten als deine floats, d.h. dass die Werte ungenauer sind.

    Einen echten Datentyp mit 17Bit zu basteln ist unmöglich, du musst irgendwie rechnen um die Daten in andere Datentypen zu verpacken. Und die schwierige Stelle beim Rechnen sind die Umbrüche. Du kannst den Speicher nur auf ein char genau (d.h. in der Regel 8 Bit) genau adressieren. Das heißt du wirst Werte haben, die du aufteilen musst.

    Bevor ich zu sehr ins Detail gehe, hier noch eine deutlich einfachere, aber nicht ganz so effiziente Möglichkeit:

    struct foo
    {
      long wert1: 17;
      long wert2: 17;
      long wert3: 17;
      long wert4: 17;
      long wert5: 17;
      long wert6: 17;
      long wert7: 17;
      long wert8: 17;
    };
    
    #include <iostream>
    
    int main()
    {
      std::cout << sizeof(foo) << '\n';
    }
    

    Da der Compiler nicht umbrechen kann, sondern nur packen, sollte da ein Wert wie 24 herauskommen, optimal wären 17. Aber immer noch besser als die 32 die du mit deinen floats haben würdest.

    Insgesamt wäre das ein sehr sehr hoher Aufwand um lächerlich wenig einzusparen. Wenn die Daten nicht gerade per Dosentelefon übertragen werden, solltest du keinen Unterschied merken.



  • Unglaublich, der GCC 4.6 von Ideone macht hieraus 32 Byte 😮
    http://ideone.com/Mdx6Z


  • Mod

    314159265358979 schrieb:

    Unglaublich, der GCC 4.6 von Ideone macht hieraus 32 Byte 😮
    http://ideone.com/Mdx6Z

    Weil beim GCC ints 32-Bit haben. Mit long sind's 24.



  • Was macht das für einen Unterschied? 17 Bit sind 17 Bit. Versteh ich nicht.



  • Wir wollen Daten aus einem Modellflugzeug per Modem zum Boden schicken. Da man die Datenrate nicht mehr erhöhen kann muss an der Datenmenge geschliffen werden.

    Je genauer die Daten sind desto besser, denn diese sollen am Boden über längerer Zeit aufintegriert werden und da können Abweichungen nach 30min schon ins Gewicht fallen...


  • Mod

    314159265358979 schrieb:

    Was macht das für einen Unterschied? 17 Bit sind 17 Bit. Versteh ich nicht.

    Der Compiler kann/darf nicht umbrechen. In einen 32-Bit Wert bekommst du eben nur einen 17-Bit Wert rein, daher braucht es 8 Stück davon. Wenn der long 64-Bit hat, kann der Compiler 3 reinpacken, wodurch er insgesamt nur 3 longs braucht, was dann 24 Byte entspricht.

    Wenn man die optimalen 17 Byte erreichen möchte, dann muss man das tatsächlich von Hand umrechnen.


  • Mod

    Alex44 schrieb:

    Wir wollen Daten aus einem Modellflugzeug per Modem zum Boden schicken. Da man die Datenrate nicht mehr erhöhen kann muss an der Datenmenge geschliffen werden.

    Je genauer die Daten sind desto besser, denn diese sollen am Boden über längerer Zeit aufintegriert werden und da können Abweichungen nach 30min schon ins Gewicht fallen...

    Ich glaube nicht, dass dir irgendjemand hier ingenieurstechnische Entscheidungen abnehmen kann. Wir können dir nur sagen: Ja es ist möglich, Daten so zu packen, es ist ein bisschen, aber nicht extrem aufwändig zu programmieren (ich schätze mal 2-3 Stunden für einen durchschnittlichen Programmierer). Ob es dir weiterhilft, 17 statt 32 Byte zu haben, ist eine technische Entscheidung. Ob die Werte genau genug oder nicht, kann man durch Mathematik entscheiden, indem man sich akzeptable Fehlerschranken vorgibt und diese mit den aufintegrierten Fehlern vergleicht (wenn du nicht weißt, was ich meine: im Matheforum das Problem beschreiben und fragen).

    Im übrigen ist mir auch nicht klar, was an den 17 Bit so besonders sein soll. Deine Analogie zwischen den Zahlenwerten von 2*Pi und 2^17 ist, höflich ausgedrückt, Unsinn.



  • Also denn werde ich die Zahl aus dem float in int16

    2π=6,2831853072
    transfomieren
    6,2831853072*5000=31416
    zurücktransformieren
    31416/5000=6,2832
    Fehler: -0,0002338435%

    würde das jetzt so schreiben (die float-Werte sind feste vorgegebene Eingangswerte):

    float ein = 6,283185;
    int16 trans;
    trans = ein*5000;
    


  • Alex44 schrieb:

    Wir wollen Daten aus einem Modellflugzeug per Modem zum Boden schicken. Da man die Datenrate nicht mehr erhöhen kann muss an der Datenmenge geschliffen werden.

    Also brauchst du keinen 17 Bit großen Datentypen, du willst nur mehr Info's in 32 Bit packen. Hilft dir vielleicht so ein Gefummel?
    http://ideone.com/9Op6X



  • SeppJ schrieb:

    Im übrigen ist mir auch nicht klar, was an den 17 Bit so besonders sein soll. Deine Analogie zwischen den Zahlenwerten von 2*Pi und 2^17 ist, höflich ausgedrückt, Unsinn.

    Ich muss Winkel von -2π bis +2π senden.
    π*10.000=31.415,9 das liegt also nur knapp unter dem von 2¹⁶.
    Nun dachte ich mir wegen der Vorzeichen wäre 2¹⁷ doch schick. Aber wie ich sehe gibt es da Grenzen. War auch zu erwarten, denn sonst hätte ich bestimmt schon irgendwo sowas gefunden.
    Aber mit Faktor 5000 passt die Zahl dann auch in ein int16 hinein und hat nur die halbe Datengröße. Ergo kann ich doppelt so viele Daten schicken...


  • Mod

    Alex44 schrieb:

    Ich muss Winkel von -2π bis +2π senden.
    π*10.000=31.415,9 das liegt also nur knapp unter dem von 2¹⁶.
    Nun dachte ich mir wegen der Vorzeichen wäre 2¹⁷ doch schick. Aber wie ich sehe gibt es da Grenzen. War auch zu erwarten, denn sonst hätte ich bestimmt schon irgendwo sowas gefunden.

    Irgendwelche Ähnlichkeiten in der Dezimaldarstellung sind reiner Zufall und haben keine tiefere Bedeutung. Da kann man nichts besonderes ausnutzen. Du muss bloß festlegen, welche Genauigkeit dir reicht und mit der Arbeitest du dann. Ist 1% pro Wert ok? 0.1%? 0.01%? Dies ist die Frage, die du dir stellen musst, nicht irgendwelche esoterischen Zahlenspiele.

    Ergo kann ich doppelt so viele Daten schicken...

    Du kannst doppelt so viele Daten mit halber Genauigkeit schicken...



  • SeppJ schrieb:

    Du kannst doppelt so viele Daten mit halber Genauigkeit schicken...

    Naja ich denke, für mich ist eine Genauigkeit von -0,0002338435 % mehr als ausreichend. Und klar ist das mit dem 2pi und der 2¹⁶ Zufall. Aber in dem Fall ist er günstig 🕶

    Bin bloß nicht auf die 5000 gekommen. Irgendwie hatte ich bei 10.000 eine Blockade

    Aber auf jeden Fall wieder eine lehrreiche Diskussion 👍

    Danke euch 😉


  • Mod

    Alex44 schrieb:

    Aber in dem Fall ist er günstig 🕶

    Nein, ist es nicht. Es wäre genau das gleiche, egal welche Dezimaldarstellung die Zahlen haben. Der Unterschied ist bloß, dass die 5000 in Dezimaldarstellung einigermaßen gerade ist. Aber das ist auch nur so, weil du nicht genau gerechnet hast. Wenn du deine Zahlen 0 bis 2 Pi auf die natürlichen Zahlen 0 bis 2^16 abbilden möchtest, dann musst du sie mit 10429, nicht mit 10000, multiplizieren. Da du nicht selber rechnest, sondern einen Computer benutzt, sind krumme Zahlen irrelevant.


  • Mod

    Telemetriedaten sind selten völlig unabhängig voneinander. Anstatt also die Genauigkeit von vornherein zu begrenzen, ist es möglicherweise zweckmäßiger, zunächst einmal bestehende Abhängigkeiten auszunutzen. Man könnte z.B. mit deltas arbeiten, da die Werte i.d.R. nicht stark schwanken werden. Dann könnte man über Kompression nachdenken.



  • Alex44 schrieb:

    Je genauer die Daten sind desto besser, denn diese sollen am Boden über längerer Zeit aufintegriert werden und da können Abweichungen nach 30min schon ins Gewicht fallen...

    Und wie sehen die Daten aus? Davon hängt ab, wie man sie mit den wenigsten Verlusten packen kann.

    Im Falle des Integrierens, tu die Simpson-Regel auf voller Genauigkeit lokal ausführen und schicke gelegentlich das Ergebnis. Oder?


Anmelden zum Antworten