liczby rzeczywiste - delphi 7

0

Witam,
zapewne dla osób programujących na liczbach zmiennoprzecinkowych to błachostka, ale ja nie mam w tym doświadczenia. Poniżej kod małej, lamerskiej procedurki pokazującej o co mi chodzi:

procedure TForm1.Button1Click(Sender: TObject);
var
  calosc      : integer;
  dziesietna  : integer;
  lancuch     : string;
  suma        : single;   //extended
  licznik     : integer;
begin
  randomize();
  suma:= 0;

  for licznik:= 0 to 1000 do
    begin
      calosc:= random(11);
      dziesietna:= random(100);
      lancuch:= IntToStr(calosc)+','+IntToStr(dziesietna);
      suma:= suma + StrToFloat(lancuch);
      Memo1.Lines.Add(FloatToStr(suma));
    end;
end;

Dlaczego kiedy operuję na zmiennej typu EXTENDED wszystko jest oki, a kiedy zmienię ją na SINGLE to program wyrzuca śmieci po przecinku? (kiedy dam real to większość jest ok, ale czasem też się śmieci zdarzą).
Nie ukrywam, że używanie extended jest dla mnie co najmniej niewykonalne ze względu na operowanie gigantycznymi ilościami danych (dane giełdowe).

JEŻELI ZNASZ ODPOWIEDŹ DOBRY CZŁOWIEKU, PROSZĘ PODZIEL SIĘ. Wiem, że dla niektórych to 'pikuś', ale ja nigdy nie siedziałem we 'flołtach' w żadnych ze znanych mi języków.

0

Hm...
DecimalSeparator := ',';

0

eeeee, chyba się nie zrozumieliśmy :)
Sprawa z separatorem (również TFormatSettings) jest mi znana.

Chodzi o to że powyższy kod generuje liczby mające zawsze 2 liczby po przecinku. Suma jakiejkolwiek ilości liczb rzeczywistych powinna dać ZAWSZE liczbę też zawierającą 2 cyfry po przecinku (i tak się dzieje ze zmienną EXTENDED). Natomiast typ single daje wynik np. 5413,42822265625.

Skopiuj proszę ten kod i uruchom go ze zmienną SINGLE a potem ze zmienną EXTENDED - od razu zauważysz różnicę i to o co mi chodzi :)

0

ułamek zapisany w systemie dziesiętnym często nie może być zapisany w systemie dwójkowym i zapisywany jest w przybliżeniu. Przybliżenie natomiast zależy od samej dokładności typu, w którym chcesz to zapisać. To jest tak samo jak nie zapiszesz 1/3 jako ułamek dziesiętny, możesz jedynie przybliżenie, które zależy od tego ile miejsc po przecinku masz do dyspozycji (dla np. 3 miejsc 1/3 = 0,333 ale po zamianie na ułamek zwykły 0,333 <> 1/3).

Albo inaczej - Ty widzisz liczby dziesiętnie a komputer dwójkowo - konwersja nie zawsze jest możliwa

0

:) Wszystko co piszesz Misiekd się zgadza :).
Natomiast mi chodzi o inną rzecz.
Spójrz proszę na poniższy kod:

procedure TForm1.Button1Click(Sender: TObject);
var
    zmienna : single;
begin
    zmienna:= 0.1;
    memo1.Lines.Add(FloatToStr(zmienna));
end;

dlaczego w memo1 otrzymuję liczbę 0,100000001490116
a nie 0,1 ?
Przecież liczba 0.1 nie wybiega poza granice typu single.

0

0.1 w systemie binarnym to:
0.00011001100110011(0011)
czyli w nieskończoność, dokładnie tak samo jak 1/3 w systemie dziesiętnym, czyli to co napisał misiek.

0

_13th_Dragon i Misiekd mają całkowitą rację.
grzesiekyogi podstaw zmienna:= 0.25 i sprawdź efekt (0.25 ma skończone rozwinięcie w systemie dwójkowym). Ponadto zauważ, że typ Single ma 7-8 cyfr znaczących i z taką dokładnością 0.1 = 0.100000001490116

0

zamień single na currency a floattostr na currtostr. Typ Currency to specjalny typ stałoprzecinkowy stworzony specjalnie obliczeń walutowych. Ma "jedynie" cztery miejsca po przecinku ALE przechowuje zawsze to co w nim zapiszesz (o ile oczywiście mieści się to w jego zakresie) - czyli Twoje 0.1 będzie ZAWSZE równe 0.1

0

Faktycznie - zastosuję typ currency, ze wstępnych 'badań' jakie teraz zrobiłem tylko on 'dał rade', tymbardziej że jeżeli chodzi o pamięć to również, jak real, jest 'wart' 8 bitów. Dziękuję Wam bardzo - jak zwykle na tym forum- się nie zawiodłem :) Pozdrawiam i stawiam wirtualnego browara :) <piwo>

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