[C++] Obcięcie dalszych miejsc dziesiętnych floata

Awatar użytkownika
musialmi
Użytkownik
Użytkownik
Posty: 3466
Rejestracja: 3 sty 2014, o 13:03
Płeć: Mężczyzna
Lokalizacja: PWr ocław
Podziękował: 382 razy
Pomógł: 434 razy

[C++] Obcięcie dalszych miejsc dziesiętnych floata

Post autor: musialmi »

C++ na ekran wyświetla 6 miejsc po przecinku. Zatem obchodzą mnie tylko one. Chciałbym, żeby liczby, które wyglądają jak całkowite, wyświetlały się jako całkowite. Wymyśliłem sposób, tylko on sobie nie działa.
Mam liczbę float, która wyświetla się jako -1.000000. Nazwijmy ją "a". Postanowiłem ją potraktować sposobem, który wymyśliłem:

Kod: Zaznacz cały

int c=1000000*a;
a=(1.0*c)/1000000;
Czyli najpierw zbieram z a pierwsze 6 miejsc dziesiętnych (ewentualnie z wcześniej czymś jeszcze, tutaj -1), a potem mnożę tę liczbę przez 1.0, żeby znów otrzymać liczbę zmiennoprzecinkową i dzielę to przez milion. Powinienem wg mnie otrzymać okrągłe -1.000000. Ale niespodziewanie dostaję -0.999999. Mam dwa pytania:

1. Jak obciąć dalsze miejsca dziesiętne?
2. Czyżby int zapamiętywał jednak miejsca dziesiętne i zostają one "odblokowane" podczas mnożenia przez 1.0?
Ostatnio zmieniony 29 sty 2015, o 18:59 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
Awatar użytkownika
Dasio11
Moderator
Moderator
Posty: 10235
Rejestracja: 21 kwie 2009, o 19:04
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 40 razy
Pomógł: 2365 razy

[C++] Obcięcie dalszych miejsc dziesiętnych floata

Post autor: Dasio11 »

1. Nie da się obciąć miejsc dziesiętnych w liczbie zmiennoprzecinkowej, bo te liczby nie są trzymane w postaci rozwinięcia dziesiętnego, tylko dwójkowego. Każdy float reprezentuje liczbę postaci

\(\displaystyle{ (-1)^s \cdot 2^c \cdot \left( 1 + \frac{a_1}{2} + \frac{a_2}{4} + \ldots + \frac{a_{23}}{2^{23}} \right),}\)

gdzie \(\displaystyle{ s, a_1, \ldots, a_{23} \in \{ 0, 1 \}}\) oraz \(\displaystyle{ c \in \{ -127, \ldots, 127 \}.}\) (Są jeszcze wartości specjalne, ale mniejsza o to).

Nie można więc dokładnie zapisać liczby -0.999999, bo ona nie jest tej postaci (nie jest ułamkiem o mianowniku \(\displaystyle{ 2^{23}}\)).

2. Nie. Typ int pamięta tylko i wyłącznie liczby całkowite, bez ukrytych miejsc po przecinku.

Obliczenia na liczbach zmiennoprzecinkowych są nie do końca dokładne (chyba jest gwarancja, że błąd względny wyniku dodawania, odejmowania, mnożenia i dzielenia jest \(\displaystyle{ \le 2^{-23}}\)). Najwyraźniej wystąpił taki właśnie drobny (ale nieunikniony) błąd w obliczeniach.


3. Jeśli chcesz liczby zmiennoprzecinkowe wyświetlać z zadaną liczbą miejsc po przecinku, to możesz najpierw wpisać napis do tablicy:

Kod: Zaznacz cały

float a = -1.0;
char c[16];
sprintf( c, "%f", a );
a potem pokombinować z tym napisem zanim wypiszesz go na ekran.
norwimaj
Użytkownik
Użytkownik
Posty: 5101
Rejestracja: 11 mar 2011, o 16:31
Płeć: Mężczyzna
Lokalizacja: 52°16'37''N 20°52'45''E
Podziękował: 4 razy
Pomógł: 1001 razy

[C++] Obcięcie dalszych miejsc dziesiętnych floata

Post autor: norwimaj »

musialmi pisze: Mam liczbę float, która wyświetla się jako -1.000000.
Czyli może być równa na przykład \(\displaystyle{ rd_{\nu}(-0.9999999).}\)
musialmi pisze:

Kod: Zaznacz cały

int c=1000000*a;
a=(1.0*c)/1000000;
Jeśli \(\displaystyle{ a=rd_{\nu}(-0.9999999),}\) to \(\displaystyle{ c=999999.}\) Nie rozumiem, dlaczego nie sprawdziłeś wartości \(\displaystyle{ c}\) przed zadaniem pytania.
Dasio11 pisze:3. Jeśli chcesz liczby zmiennoprzecinkowe wyświetlać z zadaną liczbą miejsc po przecinku, to możesz najpierw wpisać napis do tablicy:
Jeśli chcemy \(\displaystyle{ 9}\) miejsc po przecinku, to możemy napisać printf ("a=%.9f
", a);
Awatar użytkownika
Dasio11
Moderator
Moderator
Posty: 10235
Rejestracja: 21 kwie 2009, o 19:04
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 40 razy
Pomógł: 2365 razy

[C++] Obcięcie dalszych miejsc dziesiętnych floata

Post autor: Dasio11 »

norwimaj pisze:
Dasio11 pisze:3. Jeśli chcesz liczby zmiennoprzecinkowe wyświetlać z zadaną liczbą miejsc po przecinku, to możesz najpierw wpisać napis do tablicy:
Jeśli chcemy \(\displaystyle{ 9}\) miejsc po przecinku, to możemy napisać printf ("a=%.9f
", a);
Przez "zadaną" miałem na myśli, że może zależeć od liczby zer na końcu floata.
A printf ("a=%.9f
", a);
bezdusznie wyświetla 9 cyfr, czyli na przykład: -1 -> -1.000000000.
ODPOWIEDZ