Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Pętla for i liczby zmiennoprzecinkowe

Ostatnio zmodyfikowano 2011-08-27 15:33
Autor Wiadomość
devilmateo
Temat założony przez niniejszego użytkownika
Pętla for i liczby zmiennoprzecinkowe
» 2011-08-27 01:24:01
Witam.
Bawię się pętlą for i zastanawia mnie jeden fakt.
Dlaczego w przypadku:

C/C++
for( float k = 1.0; k <= 2.0; k += 0.1 )
{
    std::cout << k << ",";
}

Pętla podaje jako ostatnią wartość k=1.9.
A w przypadku gdy krok wynosi np.0.01, to ostatnią wartością w pętli jest 2.
Proszę o pomoc.
P-40020
akwes
» 2011-08-27 01:36:52
A zastanów się dlaczego:

C/C++
float a = 2.0;
double b = 2.0;

if( a == b )
     cout << "TAK!";
else
     cout << "NIE!";

Wyświetla

TAK!


Natomiast
C/C++
float a = 1.9;
double b = 1.9;

if( a == b )
     cout << "TAK!";
else
     cout << "NIE!";

Wyświetla

NIE!

A podpowiem że chodzi o reprezentacje liczb zmiennoprzecinkowych w pamięci komputera.
P-40021
devilmateo
Temat założony przez niniejszego użytkownika
» 2011-08-27 07:22:32
Podałeś float i double więc u Ciebie wystarczy że zamienię na double obie liczby i działa poprawnie.
Wiem, że float i double mają inny rozmiar w bajtach.
Ale ja użyłem tylko float, a jak zmieniłem na double to mam ten sam efekt dziwnego liczenia.
P-40025
imralav
» 2011-08-27 07:25:25
Może spróbuj dodać 'f' za wartościami zmiennych:
k=1.0f;k<2.0f;k+=0.1f
P-40026
devilmateo
Temat założony przez niniejszego użytkownika
» 2011-08-27 07:30:02
Niestety dalej to samo. I ja tam miałem k<=2.0.
A czy u Ciebie podaje dobrze wartość ta procedura?
P-40027
imralav
» 2011-08-27 07:49:08
Z tamtym dodawaniem 'f' w ciemno strzelałem ; p Czasem w SFML pomagało..
Zaraz sprawdzę kod u siebie.

#edit:
Kombinuję,ale cienki jeszcze jestem w te klocki, to moją wiedzę przekracza trochę.. Wybacz.
P-40028
akwes
» 2011-08-27 13:45:40
Tak, są różne typy, ale chciałem Ci pokazać przykład wywołany tym samym zagadnieniem i napomnieć że
Niektóre liczby zmiennoprzecinkowe nie dają się zapisać w pamięci w postaci zer i jedynek, dlatego przyjmuje się ich dość bliskie przybliżenia, które po obliczeniu wartości binarnej z wartości dziesiętnej są niedokładnym odwzorowaniem tej liczby


Czyli np. Float, który ma zakres do 7 cyfr, liczby 1.9 nie reprezentuje jako "1.9000000" tylko np. "1.9000001".
Dlatego
C/C++
float a = 1.9; // 1.9 zostaje zmienione na binarną liczbę, takiej liczby nie da się dokładnie utworzyć
// Dla komputera wiec 1.9 będzie 1.900001 (nie jest w stanie tej liczby zapisać, wiec musi iść na pewne ustępstwa)
 I co z tego wynika?
 
A no to że o ile
1.9000000 + 0.100000 = 2.000000
ale
1.9000001 + 0.100000 = 2.000001

C/C++
float a = 1.9
a += 0.1
Sprawia że a nie jest równe 2.0, ale większe.

Skąd problem z Double i Float w porównaniu? Liczba 1.9 jest liczbą felerną i jej rozwinięcie nawet dla Double nie daje się zapisać całkowicie (część ułamków ma jak gdyby nieskończone rozwinięcie dziesiętne (binarne?).
Dlatego dla double może to być:
1.90000000000001
i to również nie będzie równe dla Float 1.9 bo Float 1.9 było: 1.9000001 a sam widzisz, które jest większe
1.90000010000000
1.90000000000001
(dla estetyki przy float dodałem zero).

Tylko teraz, wszystkie liczby które podałem są przykładowe, więc może występować zupełnie inna reprezentacja danych w pamięci, ale podaję tutaj ogólną zasadę i powód takich niuansów. To nie wada języka C++, tylko binarnej reprezentacji liczb zmiennoprzecinkowych. 


 
P-40054
devilmateo
Temat założony przez niniejszego użytkownika
» 2011-08-27 15:11:47
Dziękuję za wyjaśnienie.
Chciałbym tylko jeszcze wiedzieć, co mam zrobić, żeby w pętli for występujący if porównał "i" z 0.8, i wypluł napis "cokolwiek". Skoro to nie jest 0.8 w związku z Twoją argumentacją, to jak to mogę obejść żeby uparcie to 0.8 otrzymać. Nie chciałbym mieć takich problemów w przyszłości.

C/C++
for( i = 0.0; i <= 1.0; i += 0.1 )
{
    if( i == 0.8 )
    {
        std::cout << "cokolwiek";
    }
}
P-40066
« 1 » 2
  Strona 1 z 2 Następna strona