[avr-gcc] zaokraglanie :))

Witam, mam liczbe zmienno przecinkowa i chcialbym ja zamienic na liczbe calkowita, jednak z zachowaniem zasad zaokraglania. Jaka funkcja to czyni?

Reply to
Pawel Kurzawa
Loading thread data ...

(int) (a + 0.5), na przykład

Waldek

Reply to
Waldemar

#include <stdio.h>

int main( void ) { double a=0.9999, b=1.0000; printf( "%.4lf + %.4lf = %d\n", a, b, (int) (a+b) ); return 0; }

Co otrzymamy w wyniku? Oczywiście, że jeden! Z liczbami zmienno przecinkowymi jest trochę klopotu, i trzeba być bardzo ostrożnym. Jak pamietam (x86-visual-c++-6.0) to taka funkcję (dobrą) sam musiałem sobie napisać. A zasady zaokrąglania można nietrudno zaimplementować.

Reply to
Łukasz Góralczyk

No, no, trochę przesadziłem... to nie jest takie łatwe, w zależności jakie sobie przyjmiesz założenia, do którego miejsca zaokrąglanie, ile miejsc po przecinku brać pod uwagę. Zrobienie uniwersalnej funkcji nie jest łatwe. Jeśli masz mało miejsca w swoim avr-ku to zastanowiłbym się nad implementacją stałego przecinka.

Reply to
Łukasz Góralczyk

Tue, 15 Feb 2005 22:17:57 +0100, na pl.misc.elektronika, Łukasz Góralczyk napisał(a):

Prawda, zwłaszcza że są jeszcze jakieś specjalne szczególiki wymagane w księgowości. Ale tu miało byc zwyczajne zaokrąglenie do całkowitych, IMHO ze zwyczajowym : część ułamkowa <0.5 - do dołu , >=0.5 - do góry. Wtedy wystarczy np.

int Round(double value) { double tolow=floor(value); if((value-tolow) < 0.5) return (int)tolow; else return (int)tolow+1 ; }

A i tak dużo zasobów pochłania.

Reply to
Jurek Szczesiul

Hmmm.... Nie prościej: int(value + 0.5)?

Oczywiście implementacja i sposób użycia argumentów zależny od jężyka programowania ale dotąd uzywałem zawsze (już kilkanaście lat) tego sposobu i jest niezawodny.

Reply to
RoMan Mandziejewicz

Użytkownik Łukasz Góralczyk napisał:

No oczywiście.. 1+0.999 = 1.9999, ale że konwersja (int) ucina po prostu końcówkę to dostajemy 1. Gdyby zrobić tak jak podane wyżej: (int) (a+b+0.5) byłby chyba dobry wynik ?!?

Reply to
Piotr Buczynski

Użytkownik RoMan Mandziejewicz napisał:

<ciach>

A do zaokrąglania do dowolnego miejsca po przecinku taka konwersja też sie sprawdza (oczywiście pochłania trochę liczenia ;/

float a = 1.738287; float wynik; int miejsce = 2;

wynik = ( ( (int) (a*pow(10,miejsce) + 0.5) )/pow(10,miejsce));

-> wynik == 1.7400

Nie miałem z tym raczej problemów, więc po co sobie komplikować życie ;-)

Reply to
Piotr Buczynski
[...]

[...]

Mało tego - mozna jej uzyć do zaokrąglania niekoniecznie do liczby miejsc po przecinku... Implementacja moja - ciekaw jestem, kto rozpozna język ;-) Funkcja zawiera błąd przy zaokragleniu w górę - działanie swiadome, wynikające z wiedzy, że zaokrąglana liczba nie ma aż tylu miejsc po przecinku. Napisana 11.07.1993 roku ;-)

Parametry: KWOTA - liczba do zaokrąglenia DO - z jaką dokładnością zaokrąglamy (2 miejsca po przecinku to

0.01, z dokładnością do tysięcy: 1000) - bardzo ciekawe efekty występują przy stosowaniu ciekawych liczb ;->

===8<=== PARAMETERS KWOTA, DO, METODA

DO CASE CASE M.METODA = 1 && ZAOKRĄGENIE KSIĘGOWE M.METODA = 0.5 CASE M.METODA = 2 && ZAOKRĄGLENIE W GÓRĘ M.METODA = 0.999999 CASE M.METODA = 3 && ZAOKRĄGLENIE W DÓŁ M.METODA = 0 ENDCASE

RETURN SIGN(M.KWOTA) * M.DO * INT(ABS(M.KWOTA/M.DO)+M.METODA) ===8<===

Reply to
RoMan Mandziejewicz

On Tue, 15 Feb 2005 22:44:47 +0100, Jurek Szczesiul snipped-for-privacy@wycin.ep.com.pl> wrote: [.....]

A próbowaleś przynajmniej sprawdzić jak rozwiązanie Waldka zadziała np. dla 1.49, 1.50 i 1.51? :-) A jest mniej kosztowne - tylko jedno dodawanie zmiennoprzecinkowe. Problem jest taki, że dla liczb ujemnych będzie działać niekoniecznie tak, jakbyśmy tego oczekiwali. :-) Twoje zdaje się również będzie działać w podobny sposób. :-)

Regards, /J.D.

Reply to
Jan Dubiec

On Tue, 15 Feb 2005 22:49:49 +0100, RoMan Mandziejewicz snipped-for-privacy@pik-net.pl wrote: [.....]

Dla liczb ujemnych równiez jest niezawodny? :-)

Regards, /J.D.

Reply to
Jan Dubiec

Trochę dalej podałem konkretną funkcję... Sprawdź.

Reply to
RoMan Mandziejewicz

Tue, 15 Feb 2005 22:49:49 +0100, na pl.misc.elektronika, RoMan Mandziejewicz napisał(a):

Pewnie , że prościej. Nie ma to jak sobie pokomplikować życie ;-[

Reply to
Jurek Szczesiul
15 Feb 2005 23:38:06 +0100, na pl.misc.elektronika, Jan Dubiec napisał(a):

Jasne, że spróbowałem - tylko oko krzywo spojrzało na wynik ;-[

- i nastąpiła wędrówka obwodnicą ;-)

Reply to
Jurek Szczesiul

Podana funkcja implementuje coś innego niż int(value + 0.5).

Regards, /J.D.

Reply to
Jan Dubiec

Piotr Buczynski wrote: [ciach]

Umnkęło mi, że kolega postujący chciał zaokrąglenia do liczby całkowitej

- to upraszcza problem (jeden z kolegów podał już poprawne rozwiązanie).

A co do 0.5:

#include <stdio.h>

int main( void ) { double a=0.1, b=1.0; printf( "%.4lf + %.4lf = %d\n", a, b, (int) (a+b+0.5) ); return 0; }

Powinno być 2, a jest nadal 1 :) . Pozdrawiam serdecznie.

Reply to
Łukasz Góralczyk

Chyba się nie wyspałeś. Zaokrąglenie 1.1 ma dać 2?

Reply to
RoMan Mandziejewicz

powinno być 1 i nadal jest 1. 1.0 + 0.1 = 1.1, zaokrąglone wychodzi 1.

Waldek

Reply to
Waldemar

Ej spiochy - a 0.5 widzicie ?

To co przepraszam robi avr-gcc z -1.6 przy konwersji ?

J.

Reply to
J.F.

0.5 jest 'poprawką' służacą do poprawnego zaokrąglania. I jest rzeczą oczywistą, że in(1.6) daje w wyniku 1. [...]
Reply to
RoMan Mandziejewicz

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.