[ Almedin @ 06.08.2013. 18:56 ] @
Naišao sam na sljedeći problem

Ova funkcija vraća 665

Code:
function TMainForm.f2: integer;
var
  r: double;
begin
  r := (100) * 664/100;
  Result := Math.Floor(f) + 1;
end;


Ovaj vraća 664

Code:
function TMainForm.f1: integer;
var
  r: double;
begin
  r := 664/100;
  Result := Math.Floor((100) * r) + 1;
end;


Dovoljno je da samo jednom pritisnem bilo koji taster (shift recimo) dok je program aktivan i ova druga vraća 665

Kada u unit forme kopiram Floor funkciju iz Delphi source-a

Code:
function Floor(const X: Double): Integer;
begin
  Result := Integer(Trunc(X));
  if Frac(X) < 0 then
    Dec(Result);
end;


pa nju pozivam umjesto Math.Floor, obje funkcije vraćaju istu vrijednost (665)

O čemu se ovdje radi?
[ medixsa @ 07.08.2013. 01:34 ] @


function f2: integer;
var
r: double;
begin
r := (100) * 664/100;
Result := Math.Floor(r) + 1;
end;

function f3: integer;
var
r: double;
begin
r := (100) * 664/100;
Result := Math.Floor(r) + 1;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('Rezultat br 1:'+ ' ' +inttostr(f2));
ShowMessage('Rezultat br 2:'+ ' ' +inttostr(f3));
end;


Delphi XE3 vraca isto 665
[ Almedin @ 07.08.2013. 06:51 ] @
Pa ove tvoje su obje iste kao moja f2:) Probaj f1. Interesantno je da pritisak na taster nešto mijenja.
[ ((BugA)) @ 07.08.2013. 22:13 ] @
U funkciji f2() koju si prikazao u svojoj prvoj poruci ili imas gresku u kucanju (promenljiva f koju prinosis funkciji Math.Floor()), ili je mozda u tome tvoj problem (ako je promenljiva f ipak negde deklarisana i sadrzi neku vrednost na koju moze uticati pritisak tastera).

Elem, probao sam funkcije u Delphi XE (zamenivsi gorepomenuto f sa r, pretpostavljam da ipak tako treba), i bez obzira na pritiskanje tastera u toku rada programa f2() mi uvek vraca 665, a f1() vraca 664.

Razlog za ovo ponasanje je cinjenica da funkcija Math.Floor() dolazi u tri varijante, tj. da kao parametar moze primiti promenljivu single, double ili extended tipa. Ti si u obe svoje funkcije promenljivu r deklarisao kao double, ali dok je unutar f2() samostalno prinosis kao parametar za Math.Floor() (sto poziva overload varijantu koja prima parametar tipa double), u svojoj funkciji f1() ti kao parametar za Math.Floor() prinosis (100) * r, sto uzrokuje da se u ovom slucaju poziva Math.Floor() varijanta koja prima parametar tipa extended - i stoga razlika u rezultatima / preciznosti zaokruzivanja.

Ukoliko promeljivu r u obe svoje funkcije deklarises kao extended (umesto double), obe ce vracati 665 kao rezultat. Evo jednog interesantnog linka na temu preciznoti tipova double i extended -- http://stackoverflow.com/questions/1398295/trunc-function.

p.s. Ukoliko i dalje imas problem sa razlicitim vrednostima u zavisnosti od toga da li nesto pritiskas ili ne, mozes sam debug-ovati Delphi-jeve unit-e tako sto ces ici u Project > Options > Delphi Compiler > Compiling i stiklirati "Use debug .dcus" (unutar grupe "Debugging"). Proveri samo da ti je "Build Configuration" na vrhu postavljen na "Debug". Nakon ovoga pokreni svoj program, postavi breakpoint na linije gde pozivas Math.Floor(), okini ih, i pritiskom na taster F7 (Trace Into) direktno ces uci u odgovarajucu funkciju unutar "Math.pas" unit-a (gde mozes dalje posmatrati desavanja i racunice, kao i trenutne vrednosti promenljivih).

Pozdrav, i javi sta si otkrio :)
[ Almedin @ 10.08.2013. 17:07 ] @
@((BugA)), da, f je greškom ostalo, treba r.

Evo novog testnog koda

Code:
var
  d: double;
  e: extended;
begin
  { 1 } Memo1.Lines.Add(inttostr(Floor(6.64 * 100)));
  d := 6.64;
  { 2 } Memo1.Lines.Add(inttostr(Floor(d * 100)));
  663 d := d * 100;
  { 3 } Memo1.Lines.Add(inttostr(Floor(d)));
  e := 6.64;
  { 4 } Memo1.Lines.Add(inttostr(Floor(e * 100)));
  e := e * 100;
  { 5 } Memo1.Lines.Add(inttostr(Floor(e)));
end;

Svi osim {2} odmah daju 664, dok {2} daje 663 a nakon pritiskanja bilo kog tastera daje 664.

Iz asemblerskog listinga vidim da u {2} i {3} množi double (d) sa double (100) ali u {2} sprema rezultat kao extended a u {3} kao double. U skladu sa rezultatom se poziva i odgovarajuća Floor funkcija i javlja se razlika.

Zašto se ponašanje mijenja nakon pritiska na bilo koji taster, ne znam ni kako da pokušam otkriti. Na Delphi 7 su rezultati isti ali pritiskanje tastera ne utiče na rezultat.