Skocz do zawartości

Float...okreslenie ilosci cyfr po przecinku


Pomocna odpowiedź

Ojej, to jak sobie radzisz z tak rozbudowanym hobby (LongRange FPV 10km, plus AGL odpowiednio duże by zachować łączność radiową) w obliczu przepisów obowiązujących (w całej Europie) od 1 stycznia? Masz rzecz jasna licencję na BSP, ale jaka upoważnia do takiego latania? Czy zrobiłeś już konwersję na nowe uprawnienia? Możesz coś o tym napisać? Bo moje papiery na obecne kategorie A1/A3 to przy tym pikuś, w drodze co prawda A2, ale to wciąż amatorka.

Na pewno wiesz, że na każdym modelu musisz teraz namalować swój numer licencji pilota, prawda? Bez tego dzisiaj nawet od trawy nie wolno się oderwać, chyba że to skrzydło będzie miało <250g MTOW i zero kamerek, a nie sądzę.

  • Lubię! 1
Link to post
Share on other sites
20 minut temu, marek1707 napisał:

Ojej, to jak sobie radzisz z tak rozbudowanym hobby (LongRange FPV 10km, plus AGL odpowiednio duże by zachować łączność radiową) w obliczu przepisów obowiązujących (w całej Europie) od 1 stycznia? Masz rzecz jasna licencję na BSP, ale jaka upoważnia do takiego latania? Czy zrobiłeś już konwersję na nowe uprawnienia? Możesz coś o tym napisać? Bo moje papiery na obecne kategorie A1/A3 to przy tym pikuś, w drodze co prawda A2, ale to wciąż amatorka.

Na pewno wiesz, że na każdym modelu musisz teraz namalować swój numer licencji pilota, prawda? Bez tego dzisiaj nawet od trawy nie wolno się oderwać, chyba że to skrzydło będzie miało <250g MTOW i zero kamerek, a nie sądzę.

Szczerze to nie mam papierow...latalem ostatnio w pazdzierniku...cos mi sie o uszy obilo o nowych przepisach i po tym co napisales to koniecznie musze to wszystko zweryfikowac!...nr. modelu?? Juz chyba sie im calkiem poje....w tych pustych glowkach. Co do wagi to tak...to zdazylem wyczytac, tego o zakazie kamer nie wiedzialem..(kolejna paranoja glupich ludzi)...choc Ja Ci powiem tak ze od dawna nie wolno przekraczac "pewnych" odleglosci (napewno wiesz o jakie mi chodzi) a mimo to no wiadomo co...

Link to post
Share on other sites

Nic nie pisałem o numerze modelu. Zakaz kamer i masa do 250g dotyczy latania w ogóle bez licencji, zabawkami. Gro nowych, znormalizowanych z unijnymi przepisów dotyczy przede wszystkim bezpieczeństwa osób postronnych (policz ile dżuli ma kulka z wiatrówki a ile lecący 50km/h model/kopterek 1kg) oraz lotów załogowych. Są nowe mapy obszarów powietrznych przeznaczone głównie dla modelarzy/droniarzy i generalnie BSP - tak sterowanych jak i autonomicznych. Może to Ci się podobać lub nie, ale warto poświęcić na to dwa wieczory, poczytać, zarejestrować się i zdać egzamin (nie jest trudny), bo zdaje się, że można i 5 latek dostać i nie będzie, że nie wiedziałeś.

https://drony.ulc.gov.pl/

https://droneradar.eu/

https://ulc.gov.pl/pl/drony

https://rc-fpv.pl/viewtopic.php?f=53&t=47694

 

Edytowano przez marek1707
Link to post
Share on other sites
45 minut temu, marek1707 napisał:

Na pewno wiesz, że na każdym modelu musisz teraz namalować swój numer licencji pilota, prawda?

Tutaj wspomniales o nr...

5 minut temu, marek1707 napisał:

Może to Ci się podobać lub nie, ale warto poświęcić na to dwa wieczory

Nie no ja rozumiem ze model w glupich rekach to cos strasznego...oczywiscie poczytam a nawet juz zaczalem...tylko ciezko sie w tym polapac na poczatku...a jak sprawa wyglada z odleglosciami?? Bo z tego co chyba zrozumialem jeszcze dawniej to nie istnieje cos takiego jak fpv i mozna tylko latac w zasiegu wzroku...

9 minut temu, marek1707 napisał:

ale warto poświęcić na to dwa wieczory, poczytać, zarejestrować się i zdać egzamin (nie jest trudny), bo zdaje się, że można i 5 latek dostać i nie będzie, że nie wiedziałeś.

Zgadzam sie calkowcie z Toba! Poprostu nie wiedzialem jak to wyglada w sensie testow i finansow...dlatego nie wnikalem...na wieksze odleglosci zaczalem dopiero uczeszczac okolo wakacji zeszlego roku a "modelarzem" jestem od nie calych dwoch lat..

 

 

Link to post
Share on other sites

A tutaj  tylko "zarys" tego co ten glupi Jedrus sobie wymyslil...nie ma tutaj zadnych przesuniec  itp na bitach bo to tylko przyklad zeby sobie ulatwic.

void setup() {
Serial.begin(9600);
}

void loop() {
  
float A = 23.7;
float B = 12.2;
float C = 9.3;

  Serial.print("A  (oryginal) ");
  Serial.println(A);
  Serial.print("B  (oryginal) ");
  Serial.println(B);
  Serial.print("C  (oryginal) ");
  Serial.println(C);
  Serial.println();
  delay(2000);

  A *= 10;
  B *= 10;
  C *= 10;

  Serial.print("A (mnoze * 10) ");
  Serial.println(A);
  Serial.print("B (mnoze * 10) ");
  Serial.println(B);
  Serial.print("C (mnoze * 10) ");
  Serial.println(C);
  Serial.println();
  delay(2000);

byte D = float(A);
byte E = float(B);
byte F = float(C);

  Serial.print("D (float na byte)   ");
  Serial.println(D);
  Serial.print("E (float na byte)   ");
  Serial.println(E);
  Serial.print("F (float na byte)   ");
  Serial.println(F);
  Serial.println();
  delay(2000);

D = (D & 0xff);
E = (E & 0x7f);
F = (F & 0x7f);

  Serial.print("D (8 bit)   ");
  Serial.println(D);
  Serial.print("E (7 bit)   ");
  Serial.println(E);
  Serial.print("F (7 bit)   ");
  Serial.println(F);
  Serial.println();
  delay(2000);
  Serial.println("tutaj niby przesylam 3 bajty i odbieram juz po drugiej stronie...");
  Serial.println();
A = 0;
B = 0;
C = 0;

A = byte(D);
B = byte(E);
C = byte(F);
A /= 10;
B /= 10;
C /= 10;  

  Serial.print("A (rzutowanie byte do float / 10)   ");
  Serial.println(A);
  Serial.print("B (rzutowanie byte do float / 10)   ");
  Serial.println(B);
  Serial.print("C (rzutowanie byte do float / 10)   ");
  Serial.println(C);
  Serial.println();
  Serial.println("GOTOWE");
  Serial.println();

  delay(4000);
  
}

chodzi tylko o przyklad w ktorym zamiast wysylac 12 bajtow , wysylam tyklo 3 z ta sama iloscia informacji...czyli oszczednasc spora (75%!)

  • Lubię! 1
Link to post
Share on other sites

Panowie przepraszam z gory za ponowne zawracanie glowy, ale nie moge znalezdz odpowiedzi..."zafascynowaly" mnie te liczby staloprzecinkowe po tym co napisal ethanak 

15 godzin temu, ethanak napisał:

Brawo - właśnie wynalazłeś liczby stałoprzecinkowe 😉

 i z tego co wyczytalem to tradycyjny float sklada sie z: 

1 bit

8 bit

23 bit

Natomiast staloprzecinkowa z:

16 bit

16 bit

chodzi mi o to ze nie moge znalezdz zakresu tych staloprzecinkowych po przecinku...mniej wiecej kapuje ze im wiecej bitow mam po przecinku tym wieksza mam dokladnosc (wiecej cyfr) ale mniejszy zakres calkowitych liczb Przed przecinkiem...robiac test wczoraj otrzymywalem prawidlowy wynik w tej "mojej" aplikacji i otrzymywalem liczbe 50.123456 

Gdzie liczba po przecinku wykracza poza zakres 16 bitow...

Poprostu chcialem rowniez zapytac czy wedlug tego smiesznego przykladu wyzej moge tak zmieniac liczby float i nie bede mial z tego tytulu  problemow w prostych "projektach" (w jednym miejscu przeczytalem ze staloprzecinkowe sa lepsze niz zmiennoprzecinkowe bo obliczenia sa szybsze a w innym ze duzo wad maja itp itp no i mam poprostu "mlyn" w glowie :-))

 

Link to post
Share on other sites
38 minut temu, farmaceuta napisał:

Natomiast staloprzecinkowa z:

16 bit

16 bit

Nie. Liczba stałoprzecinkowa składa się z:

  • n bit (przed przecinkiem)
  • m bit (po przecinku)

gdzie n i m są takie jakie pasują do sytuacji, a w sumie mogą dawać np 16 bitów (bo tyle wystarczy) lub nawet 8. Przykładowo - w kodzie ESP8266Audio użyto 24p8 (metoda DeltaSigma, warto zerknąć).

Link to post
Share on other sites
28 minut temu, ethanak napisał:

(metoda DeltaSigma, warto zerknąć).

Napewno zerkne 🙂

No a co do tego mojego przykladu to moge tak zamieniac float na bajty i po "rekonstrukcji" spowrotem do float liczba ta jest widziana przez program jak normalny float i nie bedzie problemu nigdzie tak?

(caly czas bardzo dziekuje za cierpliwosc i pomoc! :-))

Link to post
Share on other sites
2 minuty temu, farmaceuta napisał:

moge tak zamieniac float na bajty i po "rekonstrukcji" spowrotem do float

Jeśli będziesz się trzymał konkretnego zakresu (tzn. od 0.0 do 25.5) to tak. Strasznie skomplikowałeś te swoje obliczenia, bo wystarczyłoby pewnie coś takiego:
 

// nadajnik
uint8_t bajt = liczba * 10.0;

// odbiornik
liczba = bajt / 10.0;

Nie możesz w żaden sposób liczyc "ile razy pomnożyłeś przez dziesięć" bo taką informację musiałbyś przekazać odbiornikowi aby wiedział ile razy ma podzielić... a to już wychodzi regularny float (co prawda zdegenerowany, ale jednak float i w ośmiu bitach się nie zmieści).

Może gdybyś zamiast trzech przykładów skrzętnie dobranych tak aby się mieściły w bajcie podał rzeczywiste zakresy, coś by się pomyślało...

 

Link to post
Share on other sites
33 minuty temu, ethanak napisał:
33 minuty temu, ethanak napisał:

Jeśli będziesz się trzymał konkretnego zakresu (tzn. od 0.0 do 25.5) to tak

Bede sie tego trzymal...

Bede jeszcze mial powiedzmy

39.99 (czyli * 100 zapisane w 12 bitach)

50.123456 (czyli * 1000000 w 26 bitach) 

10.0 (tez * 10, bo liczba moze przyjac wartosc np. 7.9 w 7 bitach)

33 minuty temu, ethanak napisał:

 









// nadajnik
uint8_t bajt = liczba * 10.0;

// odbiornik
liczba = bajt / 10.0;

 

 

O ile dobrze pamietam to zapis z "twojego odbiornika" urwie mi liczbe po przecinku...czyli np. jesli podloze tu wartosc 12.3 to otrzymam juz na "wyjsciu" 12.0...robilem tak samo ale dopiero po oddzieleniu tego obliczenia do dwoch otrzymywalem 12.3

Edit.

Wroc! ...ja mnozylem i dzielilem przez 10 a nie przez 10.0......

33 minuty temu, ethanak napisał:

Nie możesz w żaden sposób liczyc "ile razy pomnożyłeś przez dziesięć" bo taką informację musiałbyś przekazać odbiornikowi aby wiedział ile razy ma podzielić... 

I to juz mamy ustalone, bo wlasnie na takim rozwiazaniu sie uparlem na poczatku, ale bede przeciez wiedzial ile i co mnoze wiec moge ustawic na "sztywno" co i jak w odbiorniku..

Edytowano przez farmaceuta
Link to post
Share on other sites

A i tak cały ten stały przecinek z częścią ułamkową to trochę oszustwo, bo przecież język C tego nie wspiera. Masz tu tylko typ całkowity (różne odmiany/długości int-ów), które nic nie wiedzą o jakimś przecinku i zmiennoprzecinkowy, z definicji "obsługujący" ułamki, o różnych zakresach dynamicznych i precyzji, zależnych od przyjętego standardu i implementacji na konkretnym procesorze. Niezależnie jednak od tego na jakim procesorze wykonujesz swój program (i jak został do tego ten kod wygenerowany) wykonywaniem arytmetyki zajmuje się arytmometr, który jest różny w zależności od procesora. Jedne procesory natywnie umieją tylko w 8-bitowe int-y, inne w 16- czy 32-bitowe, a niektóre mają wbudowaną sprzętową arytmetykę zmiennoprzecinkową. Nie wszystkie operacje i nie każda jednakowo szybko, ale jeśli masz coś takiego (tzw. FPU - Floating Point Unit) u siebie, to operacje na float-ach są praktycznie tak samo sprawnie wykonywane jak na liczbach całkowitych.

A teraz o tym "myku" z przecinkiem. Jeśli masz procesor, który ledwo sobie radzi z int-ami a arytmetyka zmiennoprzecinkowa wykonywana jest przez długie funkcje programowe (np. AVR w Arduino), to wtedy rzeczywiście opłaca się czasem trochę pokombinować z danymi i spróbować "zmusić" arytmometr do liczenia ułamków. Nie możesz tego zrobić wprost, to trochę jakbyś miał pod reką gościa który umie liczyć tylko na liczbach całkowitych, ale musisz przy jego pomocy policzyć obwód koła. Masz tam we wzorze Pi, ale gdy facet zobaczy punkt dziesiętny to zgłupieje więc nie możesz mu zapodać po prostu 2*3.14*2.53, bo policzy 2*3*2 i dostaniesz 12. Wysyłasz mu więc 2*314*253 i dostajesz wynik 158884. Ponieważ wiesz, że wszystkiego były 4 cyfry po przecinku, to przesuwasz go sobie samodzielnie i dostajesz 15.8884.

Dokładnie tak samo robisz arytmetykę ułamkową na int-ach. Bierzesz któryś typ całkowity, np. 16-bitowy unit16_t i w zależności od tego czego potrzebujesz (no, musisz to wiedzieć) wstawiasz gdzieś arbitralnie swój "wirtualny" przecinek. Niech to będzie powiedzmy między 3 a 4 bitem, czyli tworzysz format 12.4. Chcąc zakodować w nim jakąś liczbę musisz od teraz pamiętać, że bity zmieniły swoje wagi. Oryginalnie było (licząc od najstarszego):

32768, 16384, 8192, 4096, 2048, ..., 8, 4, 2, 1

a teraz masz:

2048, 1024, 512, ..., 8, 4, 2, 1, 1/2, 1/4, 1/8, 1/16

Żeby zapisać w tym formacie liczbę, której rozwinięcie dziesiętne wynosi np. 3.1415926... musisz posługiwać się tylko powyższymi wagami. Zatem dostajesz:

0000 0000 0011 0010

co oznacza:

2+1+1/8=3.125

Tak, straciłeś dokładność, ale trudno oczekiwać, że 4 bity częsci ułamkowej będą dokładnie odzwierciedlać każdy dowolny ułamek. Oczywiście niektóre będą całkiem niezłe, np. liczba 7.3125 będzie oddana z błędem zerowym:

0000 0000 0111 0101

bo rozwija się w same podwielokrotności 2 czyli:

4+2+1+1/4+1/16=7.3125

A teraz jak to pomaga w programie? Otóż arytmometr nie musi w ogóle wiedzieć o Twoich machlojkach z przecinkiem, tak jak gość od obliczeń nie wiedział, że liczy obwód koła z wykorzystaniem Pi. Załóżmy, że masz dwie zmienne w formacie 12.4 i chcesz je pomnożyć:

uint16_t a, x, y;
a = x*y;

Czy wynik tego będzie poprawny?  W pewnym sensie i tak i nie. Po otrzymaniu wyniku mnożenia od człowieka (tego z problemem punktu dzisiętnego), musiałeś dokonać korekcji położenia przecinka i tutaj musisz zrobić to samo. Jeśli mnożyłeś dwie liczby, z których każda ma 4 bity po przecinku, to w wyniku masz ich 8 z prawej strony i format 24.8. Aż 24 bitów z lewej strony przecinka arytmetyka C nie odda, bo typ wynikowy jest w tym wypadku taki jak oba wejściowe, ale na 16 bitach wyjściowego uint16_t masz po "przecinku" 8 bitów, czyli starczyło na format 8.8. Aby zachować (np. do dalszych obliczeń) przyjęty format 12.4, musisz "wygubić" nadmiarowe bity po prawej, czyli wynik przesunąć w prawo o 4 pozycje:

uint16_t a, x, y;
a = (x*y) >> 4;

Policzyłeś ułamki, a procesor i jego arytmometr nawet tego nie zauważyły 🙂 Tu widać też wadę metody: mimo, że teoretycznie masz 12 bitów przed przecinkiem, to wynik mnożenia w części całkowitej nie może być większy niż 255 (8 bitów). Podobnie rzecz jasna, choć mniej drastycznie,  jest w zwykłych int-ach, jeśli w C pomnożysz dwie zmienne typu uint16_t każda o wartości 1000 to nie dostaniesz miliona, bo wynik nie mieści się na 16 bitach.

Czy to działa? Przykład: weźmy dwie dające się dokładnie opisać w formacie 12.4 liczby, niech będzie 3.5 i 4.875. Każda z nich binarnie na 16 bitach wygląda tak:

0000 0000 0011 1000

0000 0000 0100 1110

Jeśli masz kalkulator liczący dwójkowo (w Windowsach masz) to mnożysz bezmyślnie ciagi bitów (tak jak procesor) i wychodzi:

0001 0001 0001 0000

a po korekcji o 4 pozycje w prawo:

0000 0001 0001 0001

co daje:

16+1+1/16=9.125 🙂 

Wykonując proste, całkowite mnożenie 16x16 (co i tak jest wyzwaniem dla procesorka AVR i musi tu posłużyć się funkcją w której wykona 4 mnożenia cząstkowe 8x8 i 4 sumowania wyników) oraz przesunięcie bitowe, możesz liczyć arytmetykę ułamkową. Oczywiście w dodawaniu i odejmowaniu dodatkowe bity się nie tworzą (podobnie jak w dodawaniu i odejmowaniu liczb dziesiętnych), ale w dzieleniu już trzeba uważać.

Może rozważ tego typu format? Pisaliśmy o tym wcześniej.

  • Lubię! 1
  • Pomogłeś! 1
Link to post
Share on other sites

No i poleglem...;-/ 

co prawda dopiero kilka dni "rozumiem" operacje na bitach..problem polega na tym ze jesli np. starsze bity sa zerami to mi je "urywa" (przynajmniej tak to wyglada w Serial monitorze)..

myslalem ze jesli mam bajty np...1111000 / 00011111 / 01111111 to po przesunieciach bitow bede mial np. long 00000000 11110000  00011111  01111111 a mam np. 11110000 11111 1111111...no chyba ze cos w kodzie przekrecilem...ech, opornie mi to idzie..:-/

byte tx_buf[8];

void setup() {
Serial.begin(9600);
}

void loop() {
  
float polozenie1 = 50.123456;
long polozenie3 = polozenie1 * 1000000.0;

tx_buf[0] =  (polozenie3 & 0x3ffffff) >> 18;
tx_buf[1] =  (polozenie3 & 0x3ffffff) >> 10;
tx_buf[2] =  (polozenie3 & 0x3ffffff)  >> 2;
tx_buf[3] =  (polozenie3 & 0x3ffffff)  << 6 ;

//long q = (tx_buf[0] << 18) | (tx_buf[1] << 10) | (tx_buf[2] << 2) |  (tx_buf[3] >> 6) & 0x3ffffff;

Serial.print(polozenie3, BIN);
Serial.println();
//
//Serial.println();
///Serial.print("             ");
Serial.print(tx_buf[0], BIN);
Serial.print(tx_buf[1], BIN);
Serial.print(tx_buf[2], BIN);
Serial.print(tx_buf[3], BIN);
Serial.println();
//Serial.print(q, BIN);
Serial.println();
Serial.println();
delay(3000);
}

choc patrzac na przyklady w necie to np. Sbus (protokol rc) wlasnie w taki sposob jest skladany i jakos tam nic nie ucieka a zakres liczb wynosi powiedzmy 170-1800 (16 int wpisanych do 22 bajtow) wiec czesto starsze bity sa zerami a mimo to nie znikaja...(jak prawie jakies herezje to tak jak wspominalem z liscia prosto w twarz..tylko mocno ;-))

 

Link to post
Share on other sites
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.