Jak ograniczyć liczbę zmiennoprzecinkową tylko do dwóch miejsc po przecinku w C?

215

Jak zaokrąglić liczbę zmiennoprzecinkową (taką jak 37,777779) do dwóch miejsc po przecinku (37,78) w C?

Sakib Arifin
źródło
15
Nie można poprawnie zaokrąglić samej liczby, ponieważ float(i double) nie są dziesiętnymi zmiennoprzecinkowymi - są binarnymi zmiennoprzecinkowymi - więc zaokrąglanie do pozycji dziesiętnych jest bez znaczenia. Możesz jednak zaokrąglić wynik.
Pavel Minaev
63
To nie jest bez znaczenia; to niedokładne. Jest spora różnica.
Brooks Moses
2
Jakiego zaokrąglenia oczekujesz? Half-up czy zaokrąglanie do najbliższego nawet?
Truthseeker Rangwan

Odpowiedzi:

407

Jeśli chcesz zaokrąglić liczbę do celów wyjściowych, "%.2f"łańcuch formatu jest rzeczywiście poprawną odpowiedzią. Jeśli jednak chcesz zaokrąglić wartość zmiennoprzecinkową w celu dalszego obliczenia, działa coś takiego:

#include <math.h>

float val = 37.777779;

float rounded_down = floorf(val * 100) / 100;   /* Result: 37.77 */
float nearest = roundf(val * 100) / 100;  /* Result: 37.78 */
float rounded_up = ceilf(val * 100) / 100;      /* Result: 37.78 */

Zauważ, że możesz wybrać trzy różne reguły zaokrąglania: zaokrąglaj w dół (tj. Obcinaj po dwóch miejscach dziesiętnych), zaokrąglaj do najbliższego i zaokrąglaj w górę. Zwykle chcesz zaokrąglić do najbliższego.

Jak zauważyło kilka innych, ze względu na dziwactwa reprezentacji zmiennoprzecinkowej, te zaokrąglone wartości mogą nie być dokładnie „oczywistymi” wartościami dziesiętnymi, ale będą bardzo bardzo zbliżone.

Aby uzyskać dużo (dużo!) Więcej informacji na temat zaokrąglania, a zwłaszcza zasad rozstrzygania zaokrąglania do najbliższego, zobacz artykuł w Wikipedii na temat Zaokrąglania .

Dale Hagglund
źródło
4
Czy można go zmodyfikować, aby obsługiwał zaokrąglanie z dowolną precyzją?
1
@slater Kiedy mówisz „arbitralna precyzja”, czy pytasz o zaokrąglenie do np. trzech zamiast dwóch miejsc po przecinku, czy o użycie bibliotek, które implementują nieograniczoną precyzję po przecinku? Jeśli to pierwsze, dokonaj, mam nadzieję, oczywistych zmian w stałej 100; w przeciwnym razie wykonaj dokładnie takie same obliczenia, jak pokazano powyżej, używając dowolnej biblioteki wieloprecyzyjnej, której używasz.
Dale Hagglund
2
@DaleHagglung Były, dziękuję. Czy wymagana jest korekta polegająca na zastąpieniu wartości 100 pow (10, (int) Precision)?
3
Tak. Aby zaokrąglić po k miejsc dziesiętnych, użyj współczynnika skali 10 ^ k. To powinno być naprawdę łatwe do zauważenia, jeśli wypiszesz niektóre wartości dziesiętne ręcznie i bawisz się wielokrotnościami 10. Załóżmy, że pracujesz z wartością 1.23456789 i chcesz zaokrąglić ją do 3 miejsc po przecinku. Operacja dostępna dla ciebie jest zaokrąglona do liczby całkowitej . Jak więc przesunąć pierwsze trzy miejsca po przecinku, aby pozostały one po przecinku? Mam nadzieję, że jasne jest, że pomnożymy przez 10 ^ 3. Teraz możesz zaokrąglić tę wartość do liczby całkowitej. Następnie odkładasz trzy cyfry niskiego rzędu, dzieląc przez 10 ^ 3.
Dale Hagglund
1
Czy mogę w doublesjakiś sposób sprawić, by to zadziałało ? floorceil
Wygląda
87

Używanie % .2f w printf. Drukuje tylko 2 kropki dziesiętne.

Przykład:

printf("%.2f", 37.777779);

Wynik:

37.77
Andrew Coleson
źródło
Ten sposób jest lepszy, ponieważ nie ma utraty precyzji.
albert
2
@albert Ma to również tę zaletę, że nie ma utraty floatzasięgu, ponieważ val * 100mogłoby to spowodować przepełnienie.
chux - Przywróć Monikę
42

Zakładając, że mówisz o zaokrągleniu wartości do drukowania, wtedy odpowiedzi Andrew Colesona i AraK są poprawne:

printf("%.2f", 37.777779);

Pamiętaj jednak, że jeśli chcesz zaokrąglić liczbę do dokładnie 37,78 do użytku wewnętrznego (np. Aby porównać z inną wartością), to nie jest to dobry pomysł, ze względu na sposób działania liczb zmiennoprzecinkowych: zwykle nie chcę wykonać porównania równości dla liczb zmiennoprzecinkowych, zamiast tego użyj wartości docelowej +/- wartości sigma. Lub zakoduj liczbę jako ciąg znaków ze znaną precyzją i porównaj ją.

Zobacz link w odpowiedzi Grega Hewgilla na powiązane pytanie , która obejmuje również dlaczego nie należy używać zmiennoprzecinkowego do obliczeń finansowych.

John Carter
źródło
1
Wybitny za zajęcie się pytaniem, które może stanowić pytanie (lub pytanie, które powinno być za pytaniem!). To dość ważny punkt.
Brooks Moses
W rzeczywistości 37,78 można przedstawić dokładnie przez zmiennoprzecinkowy. Liczba zmiennoprzecinkowa ma od 11 do 12 cyfr dla preission. To powinno wystarczyć, aby adresować 3778 377,8 lub wszelkiego rodzaju 4 cyfry dziesiętne.
Anonimowy Biały
@HaryantoCiu tak, w porządku, trochę poprawiłem swoją odpowiedź.
John Carter,
dynamiczna precyzja:printf("%.*f", (int)precision, (double)number);
Minhas Kamal
24

Co powiesz na to:

float value = 37.777779;
float rounded = ((int)(value * 100 + .5) / 100.0);
Daniil
źródło
4
-1: a) to nie zadziała dla liczb ujemnych (ok, przykład jest dodatni, ale nadal). b) nie wspominasz, że nie można zapisać dokładnej wartości dziesiętnej w liczbach zmiennoprzecinkowych
John Carter
32
@therefromhere: (a) Masz rację (b) Co to jest? Test w szkole średniej?
Daniil
1
dlaczego dodałeś 0,5?
muhammad tayyab
1
Konieczne jest przestrzeganie zasad zaokrąglania.
Daniil
1
zasady zaokrąglania w kontekście komentarza @Daniil są zaokrąglane do najbliższego
Shmil The Cat
20
printf("%.2f", 37.777779);

Jeśli chcesz napisać do ciągu C:

char number[24]; // dummy size, you should take care of the size!
sprintf(number, "%.2f", 37.777779);
ARAK
źródło
@ Sinan: Dlaczego edycja? @AraK: Nie, ty powinien dbać o rozmiarze :). Użyj snprintf ().
aib
1
@aib: Zgaduję, ponieważ / ** / są komentarzami w stylu C, a pytanie jest oznaczone jako C
Michael Haren
5
Tylko C89 dozwolone / ** / - styl, C99 wprowadził obsługę stylu //. Użyj kiepskiego / starego kompilatora (lub wymuś tryb C89), a nie będziesz mógł używać stylu //. Powiedziawszy to, jest rok 2009, rozważmy zarówno styl C, jak i C ++.
Andrew Coleson
11

Nie ma sposobu na zaokrąglenie a floatdo drugiego, floatponieważ zaokrąglenie floatmoże nie być reprezentowalne (ograniczenie liczb zmiennoprzecinkowych). Załóżmy na przykład, że zaokrąglasz liczbę 37,777779 do 37,78, ale najbliższa reprezentowalna liczba to 37,781.

Jednak możliwe „okrągłe” a floatza pomocą funkcji format string.

Andrew Keeton
źródło
3
Nie różni się to od powiedzenia „nie ma sposobu na podzielenie dwóch liczb zmiennoprzecinkowych i uzyskanie liczb zmiennoprzecinkowych, ponieważ podzielony wynik może nie być reprezentatywny”, co może być dokładnie prawdziwe, ale nie ma znaczenia. Pływaki są zawsze niedokładne, nawet dla czegoś tak podstawowego jak dodatek; zakłada się zawsze, że to, co faktycznie dostajesz, to „liczba zmiennoprzecinkowa, która najbardziej zbliża się do dokładnej zaokrąglonej odpowiedzi”.
Brooks Moses
Chodziło mi o to, że nie można zaokrąglić od a floatdo n miejsc dziesiętnych, a następnie oczekiwać, że wynik zawsze będzie miał n miejsc dziesiętnych. Nadal otrzymasz float, ale nie ten, którego się spodziewałeś.
Andrew Keeton
9

Ponadto, jeśli używasz C ++, możesz po prostu utworzyć taką funkcję:

string prd(const double x, const int decDigits) {
    stringstream ss;
    ss << fixed;
    ss.precision(decDigits); // set # places after decimal
    ss << x;
    return ss.str();
}

Następnie możesz wypisać dowolne podwójne myDoublez nmiejscami po przecinku z kodem takim jak ten:

std::cout << prd(myDouble,n);
synaptik
źródło
7

Nadal możesz używać:

float ceilf(float x); // don't forget #include <math.h> and link with -lm.

przykład:

float valueToRound = 37.777779;
float roundedValue = ceilf(valueToRound * 100) / 100;
ZeroCool
źródło
Obcina się w punkcie dziesiętnym (tj. Da 37) i musi zaokrąglić do dwóch miejsc po przecinku.
Pavel Minaev
Zaokrąglanie do dwóch miejsc po przecinku jest jednak trywialną odmianą (ale nadal należy wspomnieć w odpowiedzi; ZeroCool, chcesz dodać edycję?): Float roundedValue = ceilf (valueToRound * 100.0) / 100.0;
Brooks Moses
W stan snu :)
ZeroCool
Dlaczego to rozwiązanie nie jest bardziej popularne? Działa to dokładnie tak, jak powinno, przy minimalnym kodzie. Czy jest z tym jakieś zastrzeżenie?
Andy,
7

W C ++ (lub w C z rzutami w stylu C) możesz utworzyć funkcję:

/* Function to control # of decimal places to be output for x */
double showDecimals(const double& x, const int& numDecimals) {
    int y=x;
    double z=x-y;
    double m=pow(10,numDecimals);
    double q=z*m;
    double r=round(q);

    return static_cast<double>(y)+(1.0/m)*r;
}

Wtedy std::cout << showDecimals(37.777779,2);wyprodukuje: 37,78.

Oczywiście tak naprawdę nie musisz tworzyć wszystkich 5 zmiennych w tej funkcji, ale zostawiam je tam, abyś mógł zobaczyć logikę. Prawdopodobnie istnieją prostsze rozwiązania, ale działa to dla mnie dobrze - zwłaszcza, że ​​pozwala mi dostosować liczbę cyfr po przecinku, tak jak potrzebuję.

synaptik
źródło
5

Zawsze używaj do tego printfrodziny funkcji. Nawet jeśli chcesz uzyskać wartość jako liczbę zmiennoprzecinkową, najlepiej jest użyć tej opcji, snprintfaby uzyskać zaokrągloną wartość jako ciąg, a następnie przeanalizować ją z powrotem za pomocą atof:

#include <math.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

double dround(double val, int dp) {
    int charsNeeded = 1 + snprintf(NULL, 0, "%.*f", dp, val);
    char *buffer = malloc(charsNeeded);
    snprintf(buffer, charsNeeded, "%.*f", dp, val);
    double result = atof(buffer);
    free(buffer);
    return result;
}

Mówię to, ponieważ podejście pokazane w aktualnie głosowanej odpowiedzi i kilku innych tutaj - pomnożenie przez 100, zaokrąglenie do najbliższej liczby całkowitej, a następnie ponowne podzielenie przez 100 - jest błędne na dwa sposoby:

  • W przypadku niektórych wartości zaokrągli się w niewłaściwym kierunku, ponieważ mnożenie przez 100 zmienia cyfrę dziesiętną określającą kierunek zaokrąglania z 4 na 5 lub odwrotnie, z powodu niedokładności liczb zmiennoprzecinkowych
  • W przypadku niektórych wartości pomnożenie, a następnie podzielenie przez 100 nie powoduje obrócenia w obie strony, co oznacza, że ​​nawet jeśli nie nastąpi zaokrąglenie, wynik końcowy będzie nieprawidłowy

Aby zilustrować pierwszy rodzaj błędu - czasami zaokrąglanie jest nieprawidłowe - spróbuj uruchomić ten program:

int main(void) {
    // This number is EXACTLY representable as a double
    double x = 0.01499999999999999944488848768742172978818416595458984375;

    printf("x: %.50f\n", x);

    double res1 = dround(x, 2);
    double res2 = round(100 * x) / 100;

    printf("Rounded with snprintf: %.50f\n", res1);
    printf("Rounded with round, then divided: %.50f\n", res2);
}

Zobaczysz ten wynik:

x: 0.01499999999999999944488848768742172978818416595459
Rounded with snprintf: 0.01000000000000000020816681711721685132943093776703
Rounded with round, then divided: 0.02000000000000000041633363423443370265886187553406

Zauważ, że początkowa wartość była mniejsza niż 0,015, a zatem poprawna matematycznie odpowiedź przy zaokrąglaniu do 2 miejsc po przecinku wynosi 0,01. Oczywiście, 0,01 nie jest dokładnie reprezentowalny jako podwójny, ale spodziewamy się, że nasz wynik będzie podwójny najbliższy 0,01. Używanie snprintfdaje nam ten wynik, ale używanie round(100 * x) / 100daje nam 0,02, co jest błędem. Czemu? Ponieważ 100 * xdaje nam dokładnie 1,5 jako wynik. Mnożenie przez 100 zmienia zatem właściwy kierunek na zaokrąglanie.

Aby zilustrować ten drugi rodzaj błędu - wynik czasami jest źle z powodu * 100i / 100nie będąc prawdziwie odwrotności siebie - możemy zrobić podobną ćwiczenia z bardzo dużej liczby:

int main(void) {
    double x = 8631192423766613.0;

    printf("x: %.1f\n", x);

    double res1 = dround(x, 2);
    double res2 = round(100 * x) / 100;

    printf("Rounded with snprintf: %.1f\n", res1);
    printf("Rounded with round, then divided: %.1f\n", res2);
}

Nasza liczba nie ma teraz nawet części ułamkowej; jest to liczba całkowita, właśnie zapisana z typem double. Tak więc wynik po zaokrągleniu powinien być taki sam, jak na początku, prawda?

Jeśli uruchomisz powyższy program, zobaczysz:

x: 8631192423766613.0
Rounded with snprintf: 8631192423766613.0
Rounded with round, then divided: 8631192423766612.0

Ups Nasza snprintfmetoda ponownie zwraca właściwy wynik, ale podejście polegające na mnożeniu, a następnie dzieleniu na dwie części kończy się niepowodzeniem. To dlatego, że matematycznie poprawna wartość 8631192423766613.0 * 100, 863119242376661300.0nie jest dokładnie reprezentowalna jako podwójne; najbliższa wartość to 863119242376661248.0. Dzieląc to z powrotem przez 100, otrzymujesz 8631192423766612.0- inny numer niż ten, od którego zacząłeś.

Mam nadzieję, że jest to wystarczająca demonstracja, że ​​użycie roundfzaokrąglania do liczby miejsc po przecinku jest zepsute, i że powinieneś użyć snprintfzamiast tego. Jeśli czujesz, że to okropny hack, być może uspokoi cię wiedza, że ​​to właśnie robi CPython .

Mark Amery
źródło
+1 za konkretny przykład tego, co idzie nie tak z moją odpowiedzią i tymi podobnymi, dzięki dziwności zmiennoprzecinkowego IEEE i zapewniającej bezpośrednią alternatywę. Już dawno byłem peryferyjnie świadomy dużego wysiłku włożonego w drukowanie, a przyjaciele byli dla mnie bezpieczni dla wartości zmiennoprzecinkowych w obie strony. Sądzę, że praca tam wykonana może się tu pojawić.
Dale Hagglund
Ahem ... Przepraszam za słowo „sałatka” pod koniec, które jest już za późno na edycję. Chciałem powiedzieć, że „... włożono wiele wysiłku w printf i przyjaciół, aby zapewnić im bezpieczeństwo ...”
Dale Hagglund
4

Zastosowanie float roundf(float x).

„Funkcje zaokrąglania zaokrąglają argument do najbliższej wartości całkowitej w formacie zmiennoprzecinkowym, zaokrąglając przypadki o połowę od zera, niezależnie od bieżącego kierunku zaokrąglania.” C11dr §7.12.9.5

#include <math.h>
float y = roundf(x * 100.0f) / 100.0f; 

W zależności od floatimplementacji liczby, które mogą wydawać się w połowie, nie są. ponieważ zmiennoprzecinkowy jest zazwyczaj zorientowany na podstawie 2. Ponadto 0.01najtrudniejsze jest precyzyjne zaokrąglenie do najbliższego we wszystkich przypadkach „w połowie drogi”.

void r100(const char *s) {
  float x, y;
  sscanf(s, "%f", &x);
  y = round(x*100.0)/100.0;
  printf("%6s %.12e %.12e\n", s, x, y);
}

int main(void) {
  r100("1.115");
  r100("1.125");
  r100("1.135");
  return 0;
}

 1.115 1.115000009537e+00 1.120000004768e+00  
 1.125 1.125000000000e+00 1.129999995232e+00
 1.135 1.134999990463e+00 1.139999985695e+00

Chociaż „1.115” jest „w połowie drogi” między 1,11 a 1,12, po przekształceniu floatna wartość ta jest 1.115000009537...i nie jest już „w połowie drogi”, ale jest bliższa 1,12 i zaokrągla do najbliższej floatz1.120000004768...

„1,125” oznacza „w połowie drogi” między 1,12 a 1,13, w przypadku konwersji floatna wartość jest dokładnie 1.125i wynosi „w połowie”. Zaokrągla się w kierunku 1,13 ze względu na powiązania z zasadą równości i zaokrągla do najbliższego floatz1.129999995232...

Chociaż „1.135” jest „w połowie drogi” między 1,13 a 1,14, po przekształceniu floatna wartość ta jest 1.134999990463...i nie jest już „w połowie drogi”, ale jest bliższa 1,13 i zaokrągla do najbliższej floatz1.129999995232...

Jeśli użyty kod

y = roundf(x*100.0f)/100.0f;

Chociaż „1.135” jest „w połowie drogi” między 1,13 a 1,14, to po przekształceniu floatwartość jest 1.134999990463...i nie jest już „w połowie”, ale bliższa 1,13, ale niepoprawnie zaokrągla do lub floatz 1.139999985695...powodu bardziej ograniczonej precyzji floatvs. double. Ta niepoprawna wartość może być postrzegana jako poprawna, w zależności od celów kodowania.

chux - Przywróć Monikę
źródło
4

Zrobiłem to makro do zaokrąglania liczb zmiennoprzecinkowych. Dodaj go w nagłówku / pliku

#define ROUNDF(f, c) (((float)((int)((f) * (c))) / (c)))

Oto przykład:

float x = ROUNDF(3.141592, 100)

x równa się 3,14 :)

mou
źródło
Obcina to, ale pytanie wymaga zaokrąglenia. Dodatkowo podlega błędom zaokrąglania w operacjach zmiennoprzecinkowych.
Eric Postpischil,
3
double f_round(double dval, int n)
{
    char l_fmtp[32], l_buf[64];
    char *p_str;
    sprintf (l_fmtp, "%%.%df", n);
    if (dval>=0)
            sprintf (l_buf, l_fmtp, dval);
    else
            sprintf (l_buf, l_fmtp, dval);
    return ((double)strtod(l_buf, &p_str));

}

Oto nliczba miejsc po przecinku

przykład:

double d = 100.23456;

printf("%f", f_round(d, 4));// result: 100.2346

printf("%f", f_round(d, 2));// result: 100.23
użytkownik2331026
źródło
-1 z czterech powodów: 1) brak wyjaśnień, 2) podatność na przepełnienie bufora - to się przepełni, a zatem całkiem możliwe awarie, jeśli dvaljest ogromne 3) dziwne if/ elseblok, w którym robisz dokładnie to samo w każdej gałęzi oraz 4) nadmiernie skomplikowane użycie sprintfdo budowania specyfikatora formatu dla drugiego sprintfwywołania; łatwiej jest po prostu użyć .*i przekazać podwójną wartość i liczbę miejsc dziesiętnych jako argumenty do tego samego sprintfwywołania.
Mark Amery
3

Definicja kodu:

#define roundz(x,d) ((floor(((x)*pow(10,d))+.5))/pow(10,d))

Wyniki:

a = 8.000000
sqrt(a) = r = 2.828427
roundz(r,2) = 2.830000
roundz(r,3) = 2.828000
roundz(r,5) = 2.828430
Prywatność Zyp
źródło
0

Pozwól mi najpierw spróbować uzasadnić powód dodania kolejnej odpowiedzi na to pytanie. W idealnym świecie zaokrąglanie nie jest tak naprawdę wielkim problemem. Jednak w prawdziwych systemach może być konieczne zmaganie się z kilkoma problemami, które mogą spowodować zaokrąglenie, które może nie być zgodne z oczekiwaniami. Na przykład możesz wykonywać obliczenia finansowe, w których wyniki końcowe są zaokrąglane i wyświetlane użytkownikom jako 2 miejsca po przecinku; te same wartości są przechowywane ze stałą dokładnością w bazie danych, która może zawierać więcej niż 2 miejsca po przecinku (z różnych powodów; nie ma optymalnej liczby miejsc do zachowania ... zależy od konkretnych sytuacji, które każdy system musi obsługiwać, np. drobnych przedmiotów, których ceny są ułamkami grosza na jednostkę); oraz obliczenia zmiennoprzecinkowe wykonywane na wartościach, w których wyniki są plus / minus epsilon. Przez lata mierzyłem się z tymi problemami i rozwijałem własną strategię. Nie twierdzę, że napotkałem każdy scenariusz ani nie mam najlepszej odpowiedzi, ale poniżej znajduje się przykład mojego dotychczasowego podejścia, które rozwiązuje te problemy:

Załóżmy, że 6 miejsc po przecinku jest uważane za wystarczającą dokładność do obliczeń na liczbach zmiennoprzecinkowych / podwójnych (arbitralna decyzja dla konkretnego zastosowania), przy użyciu następującej funkcji / metody zaokrąglania:

double Round(double x, int p)
{
    if (x != 0.0) {
        return ((floor((fabs(x)*pow(double(10.0),p))+0.5))/pow(double(10.0),p))*(x/fabs(x));
    } else {
        return 0.0;
    }
}

Zaokrąglanie do 2 miejsc po przecinku w celu prezentacji wyniku można wykonać jako:

double val;
// ...perform calculations on val
String(Round(Round(Round(val,8),6),2));

Ponieważ val = 6.825wynik jest6.83 jak oczekiwano.

Ponieważ val = 6.824999wynik jest 6.82. Tutaj zakłada się, że obliczenia zakończyły się dokładnie6.824999 a 7. miejsce po przecinku wynosi zero.

Ponieważ val = 6.8249999wynik jest 6.83. W 9tym przypadku 7 miejsce po przecinku powoduje, że Round(val,6)funkcja daje oczekiwany wynik. W tym przypadku może występować dowolna liczba znaków końcowych9 .

Ponieważ val = 6.824999499999wynik jest 6.83. Zaokrąglanie do 8 miejsca po przecinku jako pierwszy krok, tj. Round(val,8)Zajmuje się jednym nieprzyjemnym przypadkiem, w którym obliczony wynik zmiennoprzecinkowy oblicza się 6.8249995, ale jest wewnętrznie reprezentowany jako 6.824999499999....

Wreszcie przykład z pytania ... val = 37.777779daje wynik 37.78.

Podejście to można dodatkowo uogólnić jako:

double val;
// ...perform calculations on val
String(Round(Round(Round(val,N+2),N),2));

gdzie N to precyzja, którą należy zachować dla wszystkich pośrednich obliczeń na liczbach zmiennoprzecinkowych / podwójnych. Działa to również na wartości ujemne. Nie wiem, czy takie podejście jest matematycznie poprawne dla wszystkich możliwości.

Tim D.
źródło
0

Prosty kod C do zaokrąglania liczby:

float n = 3.56;
printf("%.f", n);

Spowoduje to:

4
Aqeel Shamsudheen
źródło
-1

... lub możesz to zrobić w staromodny sposób bez żadnych bibliotek:

float a = 37.777779;

int b = a; // b = 37    
float c = a - b; // c = 0.777779   
c *= 100; // c = 77.777863   
int d = c; // d = 77;    
a = b + d / (float)100; // a = 37.770000;

To oczywiście, jeśli chcesz usunąć dodatkowe informacje z numeru.

NikosD
źródło
-2

ta funkcja przyjmuje liczbę i precyzję i zwraca zaokrągloną liczbę

float roundoff(float num,int precision)
{
      int temp=(int )(num*pow(10,precision));
      int num1=num*pow(10,precision+1);
      temp*=10;
      temp+=5;
      if(num1>=temp)
              num1+=10;
      num1/=10;
      num1*=10;
      num=num1/pow(10,precision+1);
      return num;
}

konwertuje liczbę zmiennoprzecinkową na int, przesuwając w lewo punkt i sprawdzając warunek większy niż pięć.

kapil
źródło