Często używamy mikrokontrolerów do robienia rzeczy w naszych robotach, ale musimy wykonać pewne obliczenia dziesiętne. Używanie zmiennych zmiennoprzecinkowych jest bardzo wolne, ponieważ programowa biblioteka zmiennoprzecinkowa jest automatycznie dołączana (chyba że masz wysokiej klasy mikrokontroler). Dlatego zazwyczaj używamy arytmetyki punktów stałych.
Ilekroć to robię, po prostu używam liczby całkowitej i pamiętam, gdzie jest miejsce dziesiętne. Jednak należy zadbać o to, aby wszystko było spójne, szczególnie gdy obliczenia obejmują zmienne, w których przecinek dziesiętny znajduje się w innym miejscu.
Zaimplementowałem funkcję atan2 o stałym punkcie, ale ponieważ próbowałem wycisnąć każdą ostatnią kroplę o ograniczonej precyzji (16 bitów), często zmieniałem definicję miejsca przecinka dziesiętnego i zmieniałbym się, gdy go poprawiałem. Ponadto miałbym pewne stałe, jako quasi-przeglądową tabelę, które same mają gdzieś sugerowaną kropkę dziesiętną.
Chcę wiedzieć, czy jest lepszy sposób. Czy istnieje biblioteka lub zestaw makr, które mogą uprościć stosowanie zmiennych stałoprzecinkowych, ułatwiając mnożenie i dzielenie między zmiennymi mieszanymi oraz pozwalając na deklarację liczb dziesiętnych lub wyrażeń stałych, ale automatycznie konwertując do pożądanej reprezentacji stałych punktów podczas kompilacji czas?
źródło
Odpowiedzi:
Byłoby miło, gdybyśmy mogli powiedzieć kompilatorowi zakres i precyzję każdej zmiennej wejściowej o stałym punkcie (być może żadna z dwóch nie ma punktu radix w tej samej lokalizacji), a automatycznie - w czasie kompilacji - używałby prawidłowego zakresu oraz operacje precyzji i zmiany skali dla wartości pośrednich i końcowych w szeregu obliczeń. Słyszałem pogłoski, że można to zrobić w języku programowania Ada lub w szablonach C ++.
Niestety, najbliższe, jakie widziałem, to biblioteki arytmetyczne o stałym punkcie, które wymagają od ciebie, programisty, ręcznego wyboru właściwej reprezentacji i ręcznego sprawdzenia, czy każda operacja zachowuje odpowiedni zasięg i precyzję. Czasami ułatwiają mnożenie i dzielenie między zmiennymi mieszanymi. Jak na przykład:
źródło
Użyłem TI IQMath Biblioteka wdrożyć wirtualny zmiennoprzecinkowych na ich DSP stałoprzecinkowych.
To wykorzystuje pewne rzeczy specyficzne dla TI, ale użyłem również tego kodu jako podstawy do implementacji wirtualnej matematyki zmiennoprzecinkowej na innych mikrokontrolerach. Przeniesienie zajmuje trochę pracy, ale jest o wiele łatwiejsze niż rozpoczęcie od zera.
źródło
Istnieje wiele implementacji (bez bibliotek, od razu jestem świadom) skalowania binarnego (inaczej skalowania B)
W ten sposób zapisujesz w pamięci (a nawet lepiej, dokumentujesz kod ...), gdzie znajduje się przecinek dziesiętny, używając przesunięć, aby przesunąć przecinek dziesiętny w górę lub w dół.
Użyłem skalowania B w asemblerze w projektach obronnych, nawet na najmniejszych procesorach, więc mogę ręczyć za jego przydatność do wszystkiego innego ...
źródło
W przypadku korzystania z całkowitą pamiętać gdzie „punkt” jest, są one rodzajem użyciu arytmetyki zmiennoprzecinkowej. Punkt stały, naprawdę ma punkt stały .
atan
cos
Zależy to od zakresu wartości, których potrzebuje twoja aplikacja, ale możesz chcieć całkowicie przejść do reprezentacji punktu stałego. To jest, na przykład, zamiast utrzymywania takiej liczby:
gdzie
number
jest liczba całkowita idecimal_point
mówi, gdzie jest przecinek dziesiętny, możesz zapisać go w następujący sposób:gdzie jest liczba całkowita
integer.fraction
, która ma to samo użycie pamięci, wyższy zakres wartości i ogólnie jest prostsza w użyciu.źródło
#define
, prawda? Myślałem, że faktycznie go przechowujesz i może się różnić w zależności od tego, jak duży lub mały jest twój numer.