2013-07-05 13 views
5
#include <iostream> 
using namespace std; 

int main() 
{ 
    cout.precision(32); 

    float val = 268433072; 
    float add = 13.5; 

    cout << "result =" << (val + add) << endl; 
} 

Mam kompilacji powyższy program ze standardowym g++ main.cc
i uruchomienie go z ./a.outWeird C++ unosić bug

Ouput Otrzymuję jednak,
result =268433088

Oczywiście, jest to nie jest to właściwa odpowiedź. Dlaczego tak się dzieje?

EDIT: To nie występuje podczas korzystania double w miejsce float

+9

Możesz przeczytać [Co każdy informatyk powinien wiedzieć o arytmetyki zmiennoprzecinkowej] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). –

+0

Kolejny dobry odczyt na temat zagadnień zmiennoprzecinkowych: http://stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represented-exactly-in-binary – mtrw

+3

Jakie zachowanie oczekujesz zamiast tego? (Mam na myśli to, że wypróbowałeś zarówno 'float' jak i' double', oczywiście zdajesz sobie sprawę, że 'float' ma ograniczoną precyzję.) – ruakh

Odpowiedz

8

można reprodukować swój „błąd pływać” z jeszcze prostszy kawałek kodu

#include <iostream> 
using namespace std; 

int main() 
{ 
    cout.precision(32); 
    float val = 2684330722; 
    cout << "result =" << val << endl; 
} 

Wyjście

result =2684330752 

Jak widać, dane wyjściowe nie są zgodne z wartością val została zainicjowana ed z.

Jak już wielokrotnie stwierdzono, typy zmiennoprzecinkowe mają ograniczoną precyzję. Twoja próbka kodu po prostu przekroczyła tę dokładność, więc wynik został zaokrąglony. Nie ma tu "błędu".

+0

Kto to pogardził i dlaczego? – Borgleader

1

Oprócz odniesienia do (1991, PDF) What Every Computer Scientist Should Know About Floating-Point Arithmetic

Odpowiedź jest krótka, że ​​z powodu pływak ma ograniczoną przechowywanie (podobnie jak innych prymitywów zbyt) inżynierowie musieli dokonać wyboru: które numery do przechowywania, z którymi precyzja. Dla pływających formatów punktowych postanowili zapisać numery małej wielkości dokładnie (niektóre cyfry dziesiętne), lecz liczby dużej wielkości bardzo nieprecyzyjnie, w rzeczywistości zaczynając + -16,777,217 te zakodowania numery stają się tak cienkie, że nawet nie wszystkie liczby całkowite są reprezentowane, co jest tym, co zauważyłeś.