• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Operacje na większych liczbach niż int

Object Storage Arubacloud
0 głosów
326 wizyt
pytanie zadane 11 czerwca 2015 w C i C++ przez Lexander Nowicjusz (210 p.)
Moje pierwsze pytanie, witajcie :)

Tworzę na mikrokontrolerze w języku C prędkościomierz do roweru i wyłożyłem się na równaniu, które źle liczy. Równanie jest następujące:

uint8_t predkosc=obwodkola*(obrotySek[4]+obrotySek[3]+obrotySek[2]+obrotySek[1]+obrotySek[0])*36/500;

prędkość jest małą wartością, więc uint8_t jej wystarczy. Problem w tym, że przed podzieleniem liczby w równaniu na 500 zdecydowanie wykracza ona poza inta (który w C jest dwubajtowy), przez co wyniki dla wartości większej niż kilka kilometrów są zbyt duże. Co mogę z tym zrobić?

2 odpowiedzi

0 głosów
odpowiedź 11 czerwca 2015 przez Radfler VIP (101,030 p.)

Użyj typu uint_least32_t, a równanie zrób tak:

uint8_t predkosc = 
obwodkola * (obrotySek[4]+obrotySek[3]+obrotySek[2]+obrotySek[1]+obrotySek[0])
* (uint_least32_t)36 / 500; // Użyj rzutowania 

Mogę się bardzo mylić, jednak wydaje mi się to słuszne :v

komentarz 11 czerwca 2015 przez Lexander Nowicjusz (210 p.)
zakres się zwiększył, dochodzi do 25 km/h.

Ale dla wielu obrotów na sekundę wyświetla np. 1,6 km/h, czyli jednak to nie to.

To, że obwodkola i obrotySek też są na uint8_t nie jest żadną przeszkodą?
komentarz 11 czerwca 2015 przez Radfler VIP (101,030 p.)

Nie, to raczej nie jest przeszkodą, jednak możesz spróbować podmienić typy na np. uint_least64_t (zakres: 0 - 18446744073709551615).

0 głosów
odpowiedź 11 czerwca 2015 przez hit02 Nałogowiec (33,970 p.)

Rozwiązania są dwa. Możesz pójść na łatwiznę i użyć typu double (chyba, że nie masz koprocesora, to w tedy możliwe, że będą problemy - nie wiem) lub zrobić to za pomocą bigNum'ów, czyli zaimplementować funkcje od operacji na strukturach opisujących duże liczby.

PS Możessz też spróbować czegoś takiego:

uint8_t predkosc = 0;
for(int i = 0; i < 4; i++)
{
    predkosc += obrotySek[i] * obwodkola * 36 / 500;
}

aby nie mnożyć sumy liczb, lecz każdą oddzielnie.cheeky

komentarz 11 czerwca 2015 przez Lexander Nowicjusz (210 p.)
edycja 11 czerwca 2015 przez Lexander

Może w innym miejscu leży błąd, bo nawet mnożenie każdej liczby oddzielnie daje ten sam rezultat. Pokażę kod całej funkcji (podane na górze wartości są przykładowe, do testów):


uint8_t obrotySek[5];
//ilosc obrotow w kazdej sekundzie ostatnich 5 sekund

unsigned int obwodkola=100;

unsigned long int czasJazdy=46024; //w sekundach
unsigned long int przejechanaDroga=58263; //w metrach
uint8_t predkosc=1;
uint8_t sredniaPredkosc=34;
uint8_t maxPredkosc=67;

void przeliczRower()
{
	if (obrotySek[0]==0 & obrotySek[1]==0) predkosc=0;
	else for(int i = 0; i < 4; i++)
	{
	    predkosc += obrotySek[i] * obwodkola * 36UL / 500;
	}

	obrotySek[4]=obrotySek[3]; //to mozna zrobic petla for
	obrotySek[3]=obrotySek[2];
	obrotySek[2]=obrotySek[1];
	obrotySek[1]=obrotySek[0];
	obrotySek[0]=0;

	if (predkosc) czasJazdy++;
	if (predkosc)
	{
		przejechanaDroga+=predkosc*1000UL*obrotySek[1]/3600;
	}
	sredniaPredkosc=przejechanaDroga/czasJazdy;
	if (predkosc>maxPredkosc) maxPredkosc=predkosc;
}

Wartości zmiennej przejechanaDroga też szwankują, czasem rosną, czasem maleją, nie wiem czy one też się nie przepełniają, czy to może jednak wina prędkości. Wszystko jest na typie unsigned, więc moim zdaniem nie powinno nigdzie przyjmować wartości ujemnych (nie mam jeszcze dużego doświadczenia, więc może bzdury gadam).

komentarz 12 czerwca 2015 przez hit02 Nałogowiec (33,970 p.)

Najlepiej sprawdź wartości zmiennych na każdym etapie, bo może wyliczanie w tej funkcji jest poprawne, ale na przykład gdzieś źle traktujesz dane. Jeśli na mikrokontrolerze masz dostęp do debuggera najlepiej Source Level, to luksus, bo możesz sobie sprawdzać wszystko bez wypisywania na ekran.

Nie możesz pracować na braku danych a zdaje mi się, że tak jest, bo nie wiesz do końca, gdzie jest błąd. smiley Możesz też uruchomić program na komputerze, wtedy na pewno będziesz miał debugger (np. gdb) i będziesz mógł sprawdzić, czy to błąd w logice, czy nie uwzględniłeś jakiejś właściwości procesora, na który piszesz.

Podobne pytania

+1 głos
4 odpowiedzi 1,777 wizyt
0 głosów
0 odpowiedzi 134 wizyt
pytanie zadane 23 listopada 2020 w Nasze projekty przez overcq Pasjonat (21,710 p.)
0 głosów
2 odpowiedzi 436 wizyt
pytanie zadane 8 września 2021 w Java przez Mateusz85 Początkujący (370 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...