Skocz do zawartości

Brak cyfr po przecinku w działaniu arytmetycznym


Dzonzi

Pomocna odpowiedź

18 minut temu, ethanak napisał:
10 godzin temu, Zealota napisał:

Gdzie to niby pisałem o zmiennej RPM? 

A tutaj:

Hmm. Przecież jawne rzutowanie zmiennej typu int na float, nie zmienia tej zmiennej. Ona nadal jest typu int, a jedynie - jakby to powiedzieć - "kontener" na liczby się powiększa, żeby zaspokoić zmienną f i wynik jest zgodny z oczekiwaniem, tzn. z deklaracją zmiennej f, bez obcinania zakresu do int.

Natomiast zmiana z 60 na 60.0 właśnie dokonuje tej zmiany na liczbie, co oczywiście poprawnie służy zadaniu, ale wprost liczbę całkowitą zamienia na float, niepotrzebnie zaburzając logiczną deklarację zakresów zmiennych, ale o tym już pisałem wyżej.

Zatem moją intencją w powyższym zapisie było to, żeby właśnie rozszerzyć "ten kontener", a nie żeby "nadać cechy" zmiennej RPM. Oczywiście wyszła tu pewna niewiedza, bo przy okazji sprawdziłem z kompilatorem w ręce 3 zapisy dla avr-gcc bez optymalizacji.

float f = RPM*2/60.0; // wariant jeden
float f = (float)(RPM*2)/60; // wariant dwa
float f = (float)RPM*2/60; // wariant 3

Okazuje się, że pomimo poprawnej wartości dla każdego z nich jednak niektóre dadzą więcej instrukcji , a niektóre mniej.

No to zagadka. Które dają mniej, a które więcej? Bez kompilatora 🙂 Przyznaję się bez bicia, że ja nie wiedziałem, ale orłem nie jestem.

Podsumowując wątek moją główna intencją  było to, że im bardziej wzór w kodzie przypomina ten wyliczony na kartce tym lepiej, a jawne rzutowanie jest w tym przypadku lepszym, czytelniejszym rozwiązaniem, bo zakresy liczb odpowiadają ich rzeczywistym zakresom.

Jak widać to są pewne drobne niuanse, być może mało ważne w praktyce, ale raczej "rozkmina" na tym poziomie to istotna nauka programowania. Nie sądzicie?

 

Link do komentarza
Share on other sites

Wszystko niby ok - ale tylko niby.

Dzielisz liczbę impulsów przez czas pomiaru - a ten wcale nie musi być liczbą całkowitą. Wyobraź sobie dokładniejszą wersję programu, gdzie ów czas jest różnicą między pierwszym i ostatnim pomiarem (właściwie następnym po ostatnim)

 Można się bawić w milisekundy - ale tu już niedaleko do przekroczenia zakresu int. A dzienie floatów jest w AVR-ach szybsze niż dzielenie long int...

Dlatego właśnie czas pomiaru jest wartością zmiennoprzecinkową (np. 59.75).

O to mi chodziło.

Zauważ, że Ty też używasz niejawnego rzutowania - bo przecież aby wykonać dzielenie kompilator musi zmienić stałą 60 (int) na 60.0 (float). Owszem - optymalizator zrobi z tego (float) RPM/30.0, ale chyba nie o to chodzi w tym całym rzutowaniu?

Link do komentarza
Share on other sites

1 godzinę temu, ethanak napisał:

Wszystko niby ok - ale tylko niby.

Dzielisz liczbę impulsów przez czas pomiaru

1 godzinę temu, ethanak napisał:

Wyobraź sobie dokładniejszą wersję programu,

No właśnie nie chcę tu sobie na razie wyobrażać bardziej uniwersalnych, rozszerzonych przypadków, bo jeśli do nich by doszło to należałoby cały koncept zapisu przemyśleć i pewnie sposób z przecinkiem byłby bardziej na miejscu, a może jeszcze coś innego by należało użyć.

Mnie chodzi tutaj cały czas o ten konkretny przykład jaki podał autor. Można się tylko domyślać, ale jednak wszystko na to wskazuje, że chodzi mu o rozdzielczość czasu na poziomie załóżmy sekund (mogą być również minuty), nie milisekund czy jeszcze mniej. Z tego powodu tak się upieram (pewnie jednak zbyt literalnie) na te części ułamkowe, które nie są ułamkowe. Zresztą samo f to nie wiadomo do czego, czemu tam *2 itd 🙂

Tak czy siak wydaje mi się, że rozumiem tok Twojego rozumowania i raczej na pewno wnioski jakie powstały w wątku będą przydatne. Nie zamykam się całkowicie na formę zapisu z przecinkiem, być może kiedyś zajdzie potrzeba to "się użyje".

Link do komentarza
Share on other sites

9 godzin temu, Zealota napisał:

Ona nadal jest typu int, a jedynie - jakby to powiedzieć - "kontener" na liczby się powiększa, żeby zaspokoić zmienną f i wynik jest zgodny z oczekiwaniem, tzn. z deklaracją zmiennej f, bez obcinania zakresu do int.

No właśnie nie, liczba zostanie przeniesiona do nowego miejsca w pamięci z konwersją która w niektórych przypadkach może powodować stratę dokładności (jeżeli int ma więcej niż 23 bity);

https://stackoverflow.com/questions/7775129/int-to-float-conversion-produces-a-warning

9 godzin temu, Zealota napisał:

Okazuje się, że pomimo poprawnej wartości dla każdego z nich jednak niektóre dadzą więcej instrukcji , a niektóre mniej.

Obstawiam że wariant 1 i 2 - każdy tak samo będzie miał zmiennoprzecinkowe dzielenie ale tylko 3 będzie miał mnożenie.

Sprawdźmy.

AVR gcc 9.2.0:

O0:

1 - 42, 2 - 42, 3 - 61

O3:

1 - 28, 2 - 28, 3 - 39

  • Lubię! 1
Link do komentarza
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.