[ doomed @ 19.04.2004. 21:36 ] @
recimo imamo jednu naivnu funkciju koja prebacuje string u realne brojeve nesto tipa StrToInt funkcije:

Elem f-ja izgleda ovako:

function StrToReal( arg : string ) : real;
var rez : real;
i : integer;
levo, desno : string;
li, di : real;
zarez : integer;
begin

zarez := pos('.', arg);

if zarez = 0 then
begin
rez := StrToInt(arg);
Result := rez;
end;

levo := '';
for i := 1 to zarez-1 do
levo := levo + arg;

desno := '';
for i := zarez +1 to length(arg) do
desno := desno + arg;

li := StrToint(levo);
di := StrToInt(desno);

while di > 1 do
di := di/10;

rez := li + di;
Result := rez;
end;

negde u kodu funkcija se poziva sa
kolicina := StrToReal(Edit1.Text); {kolicina je tipa real}
gde je TEXT = '0.53';

Zasto ovo ne valja?
zato sto kolicina ima vrednost 0.5299999137 iako se lepo u dibageru vidi da je rez := 0.53...

Ima li neko ideju o cemu se ovde radi i kako ovo prevazici?

[ doomed @ 19.04.2004. 21:41 ] @
zaboravih reci da je u pitanju Delphi 6
[ bancika @ 19.04.2004. 23:14 ] @
sto trazis leba preko pogace :)
imas u delphiju StrToFloat, kao i Val (jos iz pascala), a ti pravis komplikovanu i sporu funkciju za konverziju
[ doomed @ 20.04.2004. 07:23 ] @
U pravu si , ali sta cu kada sam alav :))
Salu na stranu, ali sta se desava ovde? Da li je u pitanju neki bug kompajlera ili .... ?

Bojan Bašić: obrisan nepotreban citat

[Ovu poruku je menjao Bojan Basic dana 20.04.2004. u 23:32 GMT]
[ bancika @ 20.04.2004. 12:40 ] @
mislim da je kod deljenja greska, posto ti je 0.1 isto ko i 0.09999999, mada ako debuger kaze da je ono prvo...pa bem li ga, ne znam :) ko te tera da budes radoznao :)
[ morlic @ 20.04.2004. 21:26 ] @
Ukratko posto sam tanak sa vremenom:

Daleko je to od greske u kompajleru ili debuger-u. Radi se o vrlo prostoj stvari: problem pamcenja realnih brojeva u binarnom obliku. Prilikom pretvaranja jednog broja sa zarezom u binarnu reprezentaciju moze doci do odstupanja u preciznosti.

Probaj ovaj primer. Stavi dugme na formu i na OnClick stavi:

Code:

procedure TForm1.Button1Click(Sender: TObject);
Var a, b, c : double;
begin
    a := 1.345;
    b := 1.123;
    c := a+b;
    if (c = 2.468) then ShowMessage('Jednako')
                   else ShowMessage('Nije jednako');
end;


Dobices naravno da ispitivanje utvrdjuje da jednakost ne postoji. Ispravan rezultat bi dobio ako tip double zamenis sa currency. Currency tip se prilikom operacija mnozi sa 1000 i tako se zadrzava preciznost potrebnu za rad sa novcem. Takodje postoji i BCD reprezentacija decimalnih brojeva koja pamti tacne cifre ali ima i nedostataka. Takodje za Double tip preporucujem eventualno samo "<" i ">" znakove ali ne i "=" i "<>". Za ispitivanje jednakosti treba koristiti CompareValue funkciju. U principu moze i bez svega toga ali moze biti problema kao u gornjem primeru.

E sad, da skratim pricu. Postoji jos jedan problem :) Prikazivanje brojeva na ekranu. Dobar metod za ispitivanje ovog problema je koriscenje funkcije FormatFloat().

Primer:

Code:

    FormatFloat('0.00', 0.5299999137 ); // Vraca 0.53
    FormatFloat('0.0000000000', 0.5299999137 ) // Vraca 0.5299999137


Znaci i debuger mora da koristi neki format kada prikazuje vrednosti, nije toliko kriv :)


Nadam se da ovo objasnjava donekle stvar.
[ srki @ 20.04.2004. 22:44 ] @
Citat:
doomed:
negde u kodu funkcija se poziva sa
kolicina := StrToReal(Edit1.Text); {kolicina je tipa real}
gde je TEXT = '0.53';

Zasto ovo ne valja?
zato sto kolicina ima vrednost 0.5299999137 iako se lepo u dibageru vidi da je rez := 0.53...

A kako znas da je vrednost 0.5299999137?
[ doomed @ 23.04.2004. 07:34 ] @
Citat:
srki:
Citat:
doomed:
negde u kodu funkcija se poziva sa
kolicina := StrToReal(Edit1.Text); {kolicina je tipa real}
gde je TEXT = '0.53';

Zasto ovo ne valja?
zato sto kolicina ima vrednost 0.5299999137 iako se lepo u dibageru vidi da je rez := 0.53...

A kako znas da je vrednost 0.5299999137?


pa iz dibagera....neposredno pre napustanja f-je StrToReal rez je 0.53 a kada vrati rezultat kolicina postaje 0.5299.....
[ srki @ 27.04.2004. 12:16 ] @
A da li ti je kolicina isto tipa real?
Zaista je cudno sto se razlikuju rez i kolicina. Mozda je bag do kompajlera, ne bi bilo prvi put.
[ morlic @ 28.04.2004. 08:43 ] @
Kao prvo onaj tvoj primer funkcije sadrzi takvu gresku da je pravo cudo kako si dobio neki rezultat?!

Evo ispravke sa komentarom gde je ispravljeno:

Code:

function StrToReal2( arg : string ) : real;
var rez : real;
i : integer;
levo, desno : string;
li, di : real;
zarez : integer;
begin

zarez := pos('.', arg); // Ovde nisam ispravio ali samo da napomenem da je opasno
                             // u nekoj ozbiljnoj aplikaciji fiksirati decimalni separator
                             // jer je moguce da u Windows-u bude drugacije podeseno

if zarez = 0 then
begin
rez := StrToInt(arg);
Result := rez;
end;

levo := '';
for i := 1 to zarez-1 do
levo := levo + arg[i]; // izmena na sa arg na arg[i]

desno := '';
for i := zarez +1 to length(arg) do
desno := desno + arg[i]; // izmena na sa arg na arg[i]

li := StrToint(levo);
di := StrToInt(desno);

while di > 1 do
di := di/10;

rez := li + di;
Result := rez;
end;


Pozivam ovu funkciju na formi na sledeci nacin:

Code:

procedure TForm1.Button1Click(Sender: TObject);
Var r : real;
begin
  r := StrToReal2('0.53');
  Caption := FormatFloat('##0.0000000000000', r);
end;


i dobijam svuda 0.53. Ovo sam probao u Delphi-u 7 i 8.