Spatny vypocet v Cecku - datove typy?

Od: Datum: 09.02.13 16:11 odpovědí: 4 změna: 09.02.13 19:40

Zdravim Vas,
zacinam si hrat s programovani uP ARM Cortex M3, ale narazil jsem zrejme na muj zacatecnicky nedostatek / neznamost programovani v C. Pro jednoduchost sem vkladam jen samotny kod bez hlavickovych souboru:
int main(void) {
uint32_t x[2] = {0,237154};
uint32_t y[2] = {0,225296};
int16_t K,Q;

K = 1000 * (y[0] - y[1]) / (x[0] - x[1]);
Q = y[0] - (K / 1000) * x[0];

printf("%i %i
",K,Q);

while(1);
}
Problem je v tom, ze mi to nepocita spravne a zrejme tusim, ze to bude asi zlezitost ohledne datovych typu, ale nejak tomu nerozumim ... Pomuze nekdo?
Jinak spravny vysledek: K = 949 a Q = 0
Je to vlastne pocitani parametru smernice primky (y = K.x + Q), zadane dvema body.

Seznam odpovědí:
 
moment čekejte prosím, probíhá přenos dat...
Zobrazení struktury odpovědí v otázce
Skrytí struktury odpovědí v otázce
Zobrazení struktury odpovědí v otázce

 

Odpovědi na otázku:
Datum: 09.02.13 18:24

Chyba je, že používáš uint32_t (unsigned int = neznamenkové celé číslo = přirozené číslo). V části výpočtu se tam dostáváš do záporných čísel. Dej tam int32_t a mělo by ti to už jít. Aspoň co jsem u sebe zkoušel.

doplněno 09.02.13 18:36:

Stejně nejlepší kdybys použil datový typ s desetinnou čárkou, ale nevim, co ten tvůj procesor má k dispozici. Nemá třeba double32_t? Takto to bude vždy dost nepřesné. Pokud ne, tak si vzoreček uprav na Q = y[0] - (x[0]*K) / 1000; Mělo by to být přesnější.

Ohodnoceno: 0x
 
Od: mamlas
Datum: 09.02.13 18:59

Ano mas pravdu, chyba je nekde prave u tech datovych typu. Po zmene na int32_t mi to uz jede, ale nejde to vyresit jinak nez zmenou deklarace promenne? Co kdyz budu potrebovat mit deklaraci a inicializaci prave uint32_t? A pak narazim na tento vzorecek.

Jinak zkousim to na NXP LPC17xx rade.

Ja vim, ze nejlepsi by bylo pouziti datoveho typu s desetinnou carkou, ale uprimne, kdyz je potreba rychlost uP a to nekdy i v uS tak se musi proste setrit a nejjednodussi je pocitat s celymi cisly. Aspon co jsem zkousel, tak mi to vyslo tak, ze s FLOATem to bylo az 6x pomalejsi. Sice se dosahne rychleho vypoctu, ale zase na ukor presnosti, to je mi jasne (proto nasobim 1000).

Od: hm®
Datum: 09.02.13 19:36
avatar

Kdybys opravdu potřeboval zůstat s proměnnými u uint, pomohlo by tohle?
K = 1000 * (*(int32_t*)(&y) - *(int32_t*)(&y+1)) / (*(int32_t*)(&x) - *(int32_t*)(&x+1));
Q = *(int32_t*)(&y) - (K / 1000) * *(int32_t*)(&x)
Nezkusil jsem si to, takže vyzkoušej ty. Ale vzhledem k přehlednosti zápisu je stejně lepší použít int.
doplněno 09.02.13 19:43:
Snad by taky šlo deklarovat navíc: int32_t *xi=(int32_t*)x, *yi=(int32_t*)y;
a v programu místo "x" a "y" psát "xi" a "yi".
doplněno 10.02.13 08:40:

Tak mě napadlo, že jsem to asi s těmi andítky přehnal. Zřejmě bude stačit:

K = 1000 * (*(int32_t*)y - *(int32_t*)(y+1)) / (*(int32_t*)x - *(int32_t*)(x+1));
Q = *(int32_t*)y - (K / 1000) * *(int32_t*)x

Ohodnoceno: 0x
 
Datum: 09.02.13 19:40

Upřímně já ty finty, které používají procesory moc neznám a nízkoúrovňovému programování se nevěnuji. Ale když víš, že ti část výpoču může jít do záporna, tak těžko budeš počítat jen s unsigned int. Když tam jednou mícháš unsigned int a signed int, tak tam dochází k automatickému přetypování a proto ti to nevychází. Ty to přetypování můžeš vynutit, ale zas máš riziko, že ta proměnná mohla být velká a nevejde se ti tam. Takže taky jde udělat třeba:

K = 1000 * (int32_t)(y[0] - y[1]) / (int32_t)(x[0] - x[1]);

Zjisti něco o přetypování, protože v tom byla ta tvoje chyba.

Nejdřív se řeší, aby to vůbec fungovalo a pak teprve nějaké optimalizace. Někdy to ani tak rychlé nepotřebuješ. Ano, je hezké, že to je 6x rychlejší, ale když to 6x rychlejší znamená, že místo 0,002 s to bude počítat 0,012 a ty tomu nebudeš dávat miliardu vstupů a bude to jediná operace, kterou ten tvůj procesor bude dělat... Ale ber to jako můj osobní názor...

Ohodnoceno: 0x
 

 

 

Přihlásit se k odběru odpovědí z této otázky:

Neneseme odpovědnost za správnost informací a za škodu vzniklou jejich využitím. Jednotlivé odpovědi vyjadřují názory jejich autorů a nemusí se shodovat s názorem provozovatele poradny Poradte.cz

 
Copyright © 2004-2016 Poradna Poradte.cz. Všechna práva na poradně Poradte.cz vyhrazena.