Forum: Compiler & IDEs Casting (Blind für Mathe)


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Kann bitte Jemand nach dem "mehr-Augen-Prinzip" oder dem 
"nimm-das-Brett-vom-Kopf auf folgende Funktion schauen?
1
#define FIXPOINT_MOVEMENT 1000UL
2
3
void calibration(uint16_t given_l, uint16_t should_l, uint16_t given_h, uint16_t should_h, uint16_t *a, int32_t *b) {
4
uint32_t delta_given = given_h - given_l;
5
uint16_t delta_measured = should_h - should_l;
6
*a = divideCommerciallyRound(FIXPOINT_MOVEMENT * delta_given, delta_measured);
7
//*b = FIXPOINT_MOVEMENT * given_l - *a * should_l;
8
*b = 1000 * given_l - (int32_t )(*a * should_l);
9
}

Abgebildete Funktion verhält sich wie gewünscht. Zuvor war es der 
auskommentiere Teil (der nicht funktionierte).
Ich bin gezwungen sowohl das Long zu entfernen, als auch in ein int32_t 
zu casten. Doch ich erkenne gerade nicht, wieso das nötig ist :(

: Verschoben durch Moderator
von Walter T. (Gast)


Lesenswert?

Willst Du jetzt int oder uint?

von A. S. (Gast)


Lesenswert?

D a v i d K. schrieb:
> ).
> Ich bin gezwungen sowohl das Long zu entfernen, als auch in ein int32_t
> zu casten. Doch ich erkenne gerade nicht, wieso das nötig ist :(

Was funktionierte denn nicht?

Dein int32_t cast ist wirkungslos.

Also ist noch einiges im argen.

Wie groß ist int bei Dir? Wie groß Long?

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Willst Du jetzt int oder uint?

Vorzeichenbehaftet, also int.
(Es ist eine Ausgleichslinie durch 2 Punkte.
y = a*x+b;

Testwerte: (500, 495, 900, 880)
a=1039
b=-14305

Testwerte: (500, 490, 900, 860)
a=1081
b=-29690

Zweitere gibt auch nach der Korrektur schon wieder Mist raus für *b.

Kann doch nicht so schwer sein diesen JunitTest grün zu bekommen :(

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

A. S. schrieb:
> Wie groß ist int bei Dir? Wie groß Long?

INT32_MAX= 2147483647
UINT15_MAX= 65535

Unterwegs bin ich mit simavr

: Bearbeitet durch User
von D a v i d K. (oekel) Benutzerseite


Lesenswert?

*b = ((int32_t)given_l * FIXPOINT_MOVEMENT) -((int32_t)*a *should_l)

Könnte so ein Shuh draus werden?
Die Quintessenz hab ich allerdings noch nicht verstanden.

von Walter T. (nicolas)


Lesenswert?

D a v i d K. schrieb:
> UINT15_MAX= 65535

Also genau wie UINT16_MAX. Wofür dann der exotische Datentyp?

D a v i d K. schrieb:
> Kann doch nicht so schwer sein diesen JunitTest grün zu bekommen :(

Wenn es nur das ist: TEST_IGNORE().

Und wenn es tatsächlich ums saubere Implementieren geht: Schreib die 
Formeln erst einmal sauber auf ein Blatt Papier. Um dem Mittelpunkt 
zwischen den beiden Stützpunkten die Ausgleichsgerade zu entwickeln geht 
übrigens besser als das klassische a*x + b.

von A. S. (Gast)


Lesenswert?

D a v i d K. schrieb:
> A. S. schrieb:
>> Wie groß ist int bei Dir? Wie groß Long?
>
> INT32_MAX= 2147483647
> UINT15_MAX= 65535
>
> Unterwegs bin ich mit simavr

Hast Du die Frage nicht verstanden?

Für Rechnungen ist es wichtig zu wissen, ob ein int 2 oder 4 Byte hat.

Und nochmal, was wolltest du rechnen, was kam raus?

Bei 16bit für int gehen die meisten Rechnungen schief.

von Walter T. (nicolas)


Lesenswert?

Ich kann nicht mehr editieren:

Bei den Differenzen zwischen uint wird nirgendwo sichergestellt, dass 
der Minuend größer als der Subtrahend ist.

von A. S. (Gast)


Lesenswert?

D a v i d K. schrieb:
> Könnte so ein Shuh draus werden?

Der erste Cast ist unnötig. Aber werde Dir klar, ob Du signed oder 
unsigned willst.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Walter T. schrieb:
> D a v i d K. schrieb:
>> UINT15_MAX= 65535
>
> Also genau wie UINT16_MAX. Wofür dann der exotische Datentyp?
Das war natürlich ein Tippfehler mit der 15.
> D a v i d K. schrieb:
>> Kann doch nicht so schwer sein diesen JunitTest grün zu bekommen :(
>
> Wenn es nur das ist: TEST_IGNORE().
>
> Und wenn es tatsächlich ums saubere Implementieren geht: Schreib die
> Formeln erst einmal sauber auf ein Blatt Papier. Um dem Mittelpunkt
> zwischen den beiden Stützpunkten die Ausgleichsgerade zu entwickeln geht
> übrigens besser als das klassische a*x + b.

Das verstehe ich nun wirklich nicht. Ich brauche keine Normabweichung 
über die ganze Kennlinie, sondern 2 Punkte die maximal exakt sind und 
dazwischen reicht ein ungefährer Wert fürs Display.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

A. S. schrieb:
> Für Rechnungen ist es wichtig zu wissen, ob ein int 2 oder 4 Byte hat.
Worauf willst du hinaus?

> Und nochmal, was wolltest du rechnen, was kam raus?
Testwerte vom Blatt stehen oben.

von Walter T. (nicolas)


Lesenswert?

D a v i d K. schrieb:
>> Und wenn es tatsächlich ums saubere Implementieren geht: Schreib die
>> Formeln erst einmal sauber auf ein Blatt Papier.

D a v i d K. schrieb:
> Das verstehe ich nun wirklich nicht.

Das macht nichts, wenn Du es nicht verstanden hast, bevor die Formel 
komplett auf einem Blatt Papier steht.

Ab dann kann man sich den C-Quelltext angucken. Ohne wird das nur übles 
Gefuckel. Ich spreche aus Erfahrung.

: Bearbeitet durch User
von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Walter T. schrieb:
> Ich kann nicht mehr editieren:
>
> Bei den Differenzen zwischen uint wird nirgendwo sichergestellt, dass
> der Minuend größer als der Subtrahend ist.

Die Variablen _h sind in meinem System persee IMMER größer als jene mit 
_l

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Walter T. schrieb:
> komplett auf einem Blatt Papier steht.

auf dem Papier sowie in einem Tabellenkalkulationsprogramm geht die 
Formel ja auch für ALLE Testwerte auf. (Dank Fließkomma und unbegrenzten 
Stellen)

Hier bin ich nun aber auf dem avr und muss mit #include <stdint.h> 
auskommen.

von Walter T. (nicolas)


Lesenswert?

D a v i d K. schrieb:
> auf dem Papier sowie in einem Tabellenkalkulationsprogramm geht die
> Formel ja auch für ALLE Testwerte auf. (

Welche Formel? Zeig mal!

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

Walter T. schrieb:
> D a v i d K. schrieb:
>> auf dem Papier sowie in einem Tabellenkalkulationsprogramm geht die
>> Formel ja auch für ALLE Testwerte auf. (
>
> Welche Formel? Zeig mal!

korrekturformel: AnzeigeTemp= a*Temperatur_mV+b;

delta_SOLL = 900-500 = 400
delta_IST = 880-495 = 385
a = delta_SOLL/delta_IST
b = 495 -a*500 [oder] b = 880 -a*900

von Walter T. (nicolas)


Lesenswert?

Kommt in der Formel bei beiden der Randwerte das Richtige heraus?

Und passen die beiden Koeffizienten in den Wertebereich von uint16_t ?

Was erwartest Du für a?

Und wenn die Fragen beantwortet sind: Was willst Du eigentlich mit dem 
Ergebnis anfangen? Sensor kalibrieren oder einfach eine Linie auf dem 
Display darstellen?

: Bearbeitet durch User
von Walter T. (nicolas)


Lesenswert?

Ab jetzt bitte jemand anders übernehmen. Ich muss Feierabend machen.

von A. S. (Gast)


Lesenswert?

D a v i d K. schrieb:
> A. S. schrieb:
>> Für Rechnungen ist es wichtig zu wissen, ob ein int 2 oder 4 Byte hat.
> Worauf willst du hinaus?

Google mal nach "Integral Promotion". Dadurch funktioniert es halt bei 
uint16 nicht.

Aber warum beantwortest Du die Frage nicht trotzdem einfach?

D a v i d K. schrieb:
> #define FIXPOINT_MOVEMENT 1000UL
> void calibration(uint16_t given_l, uint16_t should_l, uint16_t given_h,
> uint16_t should_h, uint16_t *a, int32_t *b) {
> uint32_t delta_given = given_h - given_l;
> uint16_t delta_measured = should_h - should_l;
> *a = divideCommerciallyRound(FIXPOINT_MOVEMENT * delta_given,
> delta_measured);
> //*b = FIXPOINT_MOVEMENT * given_l - a  should_l;
> *b = 1000 * given_l - (int32_t )(a  should_l);
> }

Es wird deutlich einfacher, wenn Du dich auf int16 beschränken kannst. 
Dann werden alle Vorzeichen richtig behandelt.

Wenn dann Differenzen auftreten können, die außerhalb des Wertebereichs 
liegen, dann musst Du entweder casten, oder nacheinander rechnen oder 
eine (dummy-)0 als Long einfügen.

a) int32_t d=(uint32_t)g_h-g_l;
b) int32_t d=g_h; int32_t-=g_l;
c) int32_t d=0L + g_h - g_l;

Wenn bei dir _h immer größer ist als _g, braucht das nicht. klar.

Bei der (auskommentierten) Formel reicht entsprechend auch eine Dummy 1 
als Long

*b = FIXPOINT_MOVEMENT * given_l - 1L*a * should_l;

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.