» Poradna » Programy

Špatný výsledek v C-čku

 |   |  Microsoft Windows 7 Chrome 33.0.1750.146

Dobrý den, potřeboval bych poradit s tímto jednoduchým leč pro mě ne moc jasným kódem v C-čku:#define CONST1 16666#define WIDTH 400int main(void) {uint16_t u16_rpm = 19920;uint32_t u32_adv = 500;int16_t s16_test = (CONST1 * (WIDTH - u32_adv)) / u16_rpm;while(1) {}return 0 ;}Mohl by mi prosím někdo vysvětlit, proč mi to správně nevypočítá s16_test = -83?Zdroj: http://www.poradte.cz/pocitace-a-prislusenstvi/...

Mohlo by vás také zajímat

Odpovědi na otázku

avatar
 | Microsoft Windows XP Chrome 0.2.149.27

To se neda cist, placni to trebas do gistu a posli sem link.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Chrome 33.0.1750.146
 |   |  Microsoft Windows 7 Firefox 27.0

Protože používáš unsigned datové typy?Zkus před použití těch 2 unsigned proměnných dát explicitní přetypování na signed..

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Microsoft Windows XP Opera 9.80

A co ti to místo "-83" hází?tipl bych si, že tam naráží hrušky na jablka. Kontrolně když si vyhodíš obsah u32_adv a u16_rpm, hází ti to co za hodnoty?Případně co takhle hodit u16_rpm do uint32?

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Chrome 33.0.1750.146

18919

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Microsoft Windows XP Opera 9.80

hm, to je zajímavý. Když si před samotným výpočtem vyhodíš všechny nadefinované proměnné/konstanty na obrazovku, čísla sedí?

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Chrome 33.0.1750.146

Ano sedí.Zkusil jsem si pohrát s tím výpočtem a ono v podstatě pomohlo, když jsem přetypoval jedno zavorku:int16_t s16_test = (CONST1 * (int16_t)(SPACE_WIDTH - u32_adv)) / u16_rpm;Najednou to již počítá správně. Existují nějaká pravidla pro definování typu proměnných např. že je lepší všechny proměnné mít typu int32_t a jiné raději nepoužívat?

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Microsoft Windows XP Opera 9.80

Takže to nakonec byly ty hrušky a jabka, jak jsem tušil.Pravidla jsou taková, jaká si je programátor udělá. Ale obecně vzato je lepší programovat vlastní program s velkorysým definováním (tedy je zbytečné definovat unsigned, nebo 16bit...) a až teprve při optimalizaci programu začít škrtat. Prvně pro drtivou většinu programů uživatelů jsou výkony dnešních PC silně naddimenzovány a za druhé předejdeš právě takovým vymrdávkám, jako je je právě tento případ, kdy překladač nejspíše nezvládl se v mezipaměti vypořádat s faktem, že signed (buhví co) a unsigned (16bit integer) hodnota hází unsigned (16bit integer). A to, že se to celé ve finále ukládalo do signed 16bit integer, která má pro daný výpočet dostatečnou kapacitu (+-32768) překladač nebral v potaz. Nejspíše se přizpůsoboval proměnné s nejnižším definovaným rozsahem (uint16) a záporná hodnota ho totálně rozhodila a zvoral i následné multiplikace. Dokonce bych podle chybného výsledku tipnul, jestli si hvězdičku nevyložil jako pointer protože do výpočtu zakomponoval všechny hodnoty až na CONST1, která by ale skrze pointer měla boolean hodnotu vyjádřenou v integer jako -1.Mno, hlavně že jsi to vyřešil.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Chrome 33.0.1750.146

No ono by to nevadilo, kdyby ten program byl v PC, ale ono je to právě v ARMu M0 :)

Souhlasím  |  Nesouhlasím  |  Odpovědět
 | Microsoft Windows XP Opera 9.80

Aha tak to je jiná. Nicméně postupoval bych i zde asi stejně. Nejprve na proměnných nešetřit a až program bude fungovat, začít s optimalizacemi. pokud to bude třeba (tuším arduino na řízení nějakého vysokorychlostního motorku do letadla). Cortex M0 je docela výkonný, že by tu zpětnou vazbu mohl dávat s dostatečně krátkou prodlevou...Problém je se subdefinicemi, kterou jsi například udělal právě v tom opraveném výpočtu, tomu bych se z principu vyhnul, protože v rozsáhlejších programech to velmi komplikuje změny a optimalizace. Radši ten výpočet vyvést na více kroků a definovat proměnné, byť pracovní, mimo samotný výpočet.

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Firefox 27.0

Ono trošku záleží an překladači, ale vyhodnocení bych viděl nějak takto:Začne se nejvnitřnejší závorkou. Tam je konstanta a typ uint-> výsledek bude uint. To se násobí konstantou -> výsledek bude uint a to se dělí uintem-> výsledek bude uint, pak se to přetypuje do výsledku-> int.Po tom přetypování té závorky se tam zavleče int, což je obecnější jak uint, proto se následně používá int.K tomuhle by se mělo dát dohledat jak přesně v daném prostředí fungují defaultní konverze

Souhlasím  |  Nesouhlasím  |  Odpovědět
 |   |  Microsoft Windows 7 Firefox 27.0

Resp problém byl přesně tam, jak jsem odhadl výše-> defaultní konverze proměnných.

Souhlasím  |  Nesouhlasím  |  Odpovědět

Související témata: Špatný výsledek, Výsledek, #define, Define