Problemy z konwersją *char na float

0

Program wyciąga dane z bazy danych na MySQL'u, a wyniki zapytania są zwracane w postaci ?stringów?. Oto przykładowy kod itp:

Struktura tabeli :

CREATE TABLE tabela
(
	tabela_id  	INT UNSIGNED 	NOT NULL AUTO_INCREMENT,
	wartosc	float(7,3)		NOT NULL,
  PRIMARY KEY (tabela_id)
);

przykładowe dane

tabela_id	wartosc
1		2.300
2		3.200
3		5.250
....
// zapytanie zwracające wszystkie elementy tabeli
wynik1 = fWykonajSQL(?SELECT wartosc FROM tabela?); 
float fsuma = 0.0;

for(int i = 0; i < fIloscWierszy(wynik1); i++
	{
	fsuma += fWartoscZapytania(wynik, i);
	cout << ? element ? << i << ? = ? << fWartoscZapytania(wynik, i) << endl;
	}

// zapytanie wyliczające sumę wartości elementów z tabeli
wynik2 = fWykonajSQL(?SELECT SUM(wartosc) FROM tabela?);

cout << ?fsuma = ? << fsuma << endl;
cout << ?suma z zapytania = ? <<  fWartoscZapytania(wynik2, 0) << endl;

a wynik jest taki

element 0 = 2.300
element 1 = 3.200
element 2 = 5.250
fsuma = 10.7499999
suma z zapytania = 10.75

Wnioski: Czasem funkcja atof(?2.300?) zwraca 2.3 ale w niektórych sytuacjach wynikiem jest 2.2999999
Próbowałem znaleźć regułę w których sytuacjach wynik jest prawidłowy a w których błędny ale nic nie udało mi się wydedukować.

Jakieś rady jak z tego wybrnąć ???

0

Komputery przechowuja liczby w systemie dwojkowym, a liczba 2.3 jest w tym systemie ULAMKIEM OKRESOWYM. Czyli nie da sie go reprezentowac dokladnie. Stad masz taki dziwny wynik, choc jest on bardzo bliski prawidlowemu. Jesli taka dokladnosc Ci wystarcza, a chcesz jedynie jakos ladnie to na ekran wyswietlic, to daj printf("%.3f") - wyswietli Ci ladnie zaokraglone "2.300".

Jesli jednak robisz jakies obliczenia finansowe i nie moze byc najmniejszych bledow zaokraglen, to nie trzymaj liczb we floatach tylko w intach. Wtedy niestety musisz przed konwersja kropke "recznie" przesunac o pare miejsc w prawo (dopisujac ewentualne 0), a nastepnie ja wywalic wraz z czescia ulamkowa i wpuscic w atoi().

Jesli trzymasz zlotowki, to mozesz trzymac po prostu grosze. Przyklad:
"2.3" zl -> "230." gr -> "230" -> 230
W pamieci trzymasz wiec liczby 100 razy wieksze, a jedynie przy wyswietlaniu dzielisz je przez 100.

0

OK.
Dzięki za odpowiedź. Sprawdzę i dam znać czy proponowane rozwiązanie się sprawdziło.

1 użytkowników online, w tym zalogowanych: 0, gości: 1