Mnożenie dużych liczb w AVR C

Witam wszystkich Mam takie pytanie do praktyków piszących w C dla rodziny AVR. Jak optymalnie przydzielać rozmiar zmiennej w przypadku mnożeń liczb. Podam na przykładzie

a=250; b=250; c=250 d=?

d=a*b*c;

No własnie, ile bitów przydzielić konkretnym zmiennym? D oczywiście musi być

32 bitowa, by pomieścić wynik, ale czy A i B i C mogą być 8 bitowe? Chodzi mi o sam proces obliczeń.

Test w builderze oblicza prawidłowo to równanie, ale w AVR jak zrobiłem podobny przykład niestety dostałem śmieci. Ten przykład poniżej wyświetla mi 63236 zamiast spodziewanych 48800.

uint8_t x1,x2,x3,x4; uint16_t y1,y2,y3;

x1=250; x2=250; x3=128; x4=100;

y1=((x1*x2)/x3)*x4; wyswietl(128,30,y1);

Czy np. lewa zmienna działania musi pomieścić wynik działania? Np dla x1*x2, x1 musi być 16 bitowy? Jest jakaś regóła jakiej trzeba się trzymać? Czyli jak to robić optymalnie, bo zapewne mnożenie dwóch cyfr 16 bitowych jest znacznie szybsza od 32 bitowych, nie wspominając już o 8 bitach.

Kompilator to WinAVR ściagany może miesiac temu, wiec aktualny. Procesor to ATMEGA 128. Pamięci SRAM pod dostatkiem.

Pozdrawiam

Reply to
Michał
Loading thread data ...

Najwyrazniej mnozy ci dwa pierwsze ze znakiem.

250*250=62500= -3036

To niewatpliwie, ale ogolnie w C to malo. Jeszcze co najmniej jeden ze skladnikow powinien miec taki typ.

Przy czym AVR GCC sporo obliczen rozszerza samodzielnie do int - czesto zupelnie niepotrzebnie.

sprobuj uint16, ale moze byc za malo - tu mu wyraznie brakuje bitu znaku. bezpieczniej bedzie y1=(((long)x1*x2)/x3)*x4;

Dla takich obliczen ... zmienny przecinek :-(

J.

Reply to
J.F.

Michał pisze:

(cut)

Nie mam praktyki w AVR ale niezależnie od uC zmienne a, b, c zrób unsigned char natomiast d oczywiście 32-bit (ew. 24 jeżeli masz taką opcję). Następnie często pomaga rozbicie działania na mniejsze i konwersja typu (wskazanie kompilatorowi na jakich typach zmiennych jest to działanie).

d = (u32)a * b //tu kompilator być może wykorzysta funkcję u32*u8 d *= c // tu też

albo:

d = a; d *= b; d *= c;

Pokombinuj z takimi możliwościami, podejrzyj assemblera i zobacz co bardziej optymalne. Jeżeli jest to mnożenie liczb bez znaków to deklaruj też te liczby jako unsigned, bo będzie jak mówił ktoś wcześniej - kompilator może przyjąć że 250 = -6

pozdrawiam

Rogher

Reply to
Rogher

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.