double ve strtofloat

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
mkysoft
Kıdemli Üye
Mesajlar: 3110
Kayıt: 26 Ağu 2003 12:35
Konum: Berlin
İletişim:

double ve strtofloat

Mesaj gönderen mkysoft »

Kod: Tümünü seç

var
  test: double;
  abc: string;
begin
  abc := '0,4';
  test := strtofloat(abc);
  if test > strtofloat(abc) then showmessage('ok');
yukarıda verdiğim kod çalışarak mesaj penceresi açıyor. Oysaki açmaması gerekir. Nedenini anlayamadım.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

- Böyle durumlarda fonksiyonarın döndürdüğü ile tipin yapısını karşılaştırmak lazım..

Kod: Tümünü seç

var
  test: double;
  abc: string;
begin
  abc  := '0,4';
  test := strtofloat(abc);
  if test > strtofloat(abc) then
    showmessageFmt('%.4f (Size:%d) > %.4f (Size:%d)', [test, SizeOf(Test), strtofloat(abc), SizeOf(strtofloat(abc))]);
end;

Kod: Tümünü seç

0,4000 (Size:8) > 0,4000 (Size:10)
- Yani Double yerine Extended kullan..
Resim
Resim ....Resim
Hakan Can
Üye
Mesajlar: 634
Kayıt: 04 Mar 2005 04:27
Konum: Ankara

Mesaj gönderen Hakan Can »

Bu maalesef genel bir problem. StrToFloat Extended sonuç döndürüyor. Extended Double'a dönüşürken problemli dönüyor.

Kodun sonuna şunu ilave edersen daha iyi anlarsın:

Kod: Tümünü seç

showmessage(FormatFloat('0.00000000000000000000000000', test));
İyi çalışmalar.
mkysoft
Kıdemli Üye
Mesajlar: 3110
Kayıt: 26 Ağu 2003 12:35
Konum: Berlin
İletişim:

Mesaj gönderen mkysoft »

iki bytein hesabını yaparsak olacağı buydu :D
Aslında bende hep extended kullanırım ama bu sefer algoritma RAM'da az yer kaplasın diye böyle yapmıştım. Ne gerek var dimi tasarrufa.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@Hakan CAN bu bir problem değil...
@mrmarman yazdı:- Yani Double yerine Extended kullan..
- Fonksiyon dönüşü hangi tipte ise aynı tipte bir değişken kullanmak kuraldır. Elma <> Armut yani. ikisi de meyve olabilir ama farklı :lol: İkisi de floating point olabilir ama taşınma şekilleri farklı.

- Bu farklılıklar saklanan değer için rezerve edilen yerler dikkate alınarak oluşur. Veriler karşılaştırılırken içindeki verinin tamamı dolu varsayılarak bütün olarak değerlendirmeye alınır...
Resim
Resim ....Resim
Hakan Can
Üye
Mesajlar: 634
Kayıt: 04 Mar 2005 04:27
Konum: Ankara

Mesaj gönderen Hakan Can »

mrmarman yazdı:@Hakan CAN bu bir problem değil...
@mrmarman yazdı:- Yani Double yerine Extended kullan..
- Fonksiyon dönüşü hangi tipte ise aynı tipte bir değişken kullanmak kuraldır. Elma <> Armut yani. ikisi de meyve olabilir ama farklı :lol: İkisi de floating point olabilir ama taşınma şekilleri farklı.

- Bu farklılıklar saklanan değer için rezerve edilen yerler dikkate alınarak oluşur. Veriler karşılaştırılırken içindeki verinin tamamı dolu varsayılarak bütün olarak değerlendirmeye alınır...
Hocam dediğim işlemi yaparsanız problem olduğunu anlarsınız. Yani kodun sonuna:

Kod: Tümünü seç

showmessage(FormatFloat('0.00000000000000000000000000', test));
ilave edip deneyin. Sonuçta atanan sayı 0,4 değil onu göreceksiniz. Delphi'nin real sayılarla ilgili benzer problemleri var.

İyi çalışmalar.
Kullanıcı avatarı
sabanakman
Kıdemli Üye
Mesajlar: 3081
Kayıt: 17 Nis 2006 08:11
Konum: Ah bi Antalya olaydı keşke (Ankara)

Mesaj gönderen sabanakman »

Mrb; şu anda denemedim ama şu iki değer Turbo Pascal'da da farklı değer üretiyordu.

Kod: Tümünü seç

Sonuc:=0;
for i:=1 to 10 do Sonuc:=Sonuc+(1/i);
Sonuc2:=0;
for i:=10 downto 1 do Sonuc2:=Sonuc2+(1/i);
if Sonuc=Sonuc2 then WriteLn('Eşit') else WriteLn('Eşit Değil');
Program bana eşit olmadığını söyledi:!: Halbuki ne hayallerle eşit çıkacağını sanmıştım.:)
Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@Hakan Can

- Hala aynı hatayı yapıyorsun...
@Hakan Can yazdı:showmessage(FormatFloat('0.00000000000000000000000000', test));
Delphi Help, FormatFloat function hk. yazdı:Formats a floating point value.

Unit

SysUtils

Category

floating point conversion routines

Delphi syntax:

function FormatFloat(const Format: string; Value: Extended): string; overload;

Kod: Tümünü seç

  showmessage(FormatFloat('0.00000000000000000000000000', strtofloat(abc)));
Resim
Resim ....Resim
Hakan Can
Üye
Mesajlar: 634
Kayıt: 04 Mar 2005 04:27
Konum: Ankara

Mesaj gönderen Hakan Can »

mrmarman yazdı:@Hakan Can

- Hala aynı hatayı yapıyorsun...
@Hakan Can yazdı:showmessage(FormatFloat('0.00000000000000000000000000', test));
Delphi Help, FormatFloat function hk. yazdı:Formats a floating point value.

Unit

SysUtils

Category

floating point conversion routines

Delphi syntax:

function FormatFloat(const Format: string; Value: Extended): string; overload;

Kod: Tümünü seç

  showmessage(FormatFloat('0.00000000000000000000000000', strtofloat(abc)));
Hocam maalesef hata yapan sizsiniz.

Kodu şu şekilde test ederseniz ne demek istediğimi daha iyi anlayacaksınız:

Kod: Tümünü seç

var
  test: Double;
  abc: string;
begin
  abc := '0,4';
  test := strtofloat(abc);
  if test > 0.4 then showmessage('ok');
Normalde showmessage('ok') çalışmaması gerekiyor değil mi? Bir deneyin.

İyi çalışmalar.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

- Evet aslında şimdi birşeyin farkına vardım. O da hatanın ne olduğunu henüz algılamamış olmanız... :oops:

- Ben mi ifade edemiyorum yoksa görmek o kadar zor mu ? Önce değişkenler arası hatalı aktarım yapıyorsunuz, sonra bu hatalı sonuçla olması gerekeni karşılaştırma yapıp bana soruyu yineliyorsunuz..

- Verdiğiniz kod bloğunda ve nicelerinde sorun ne idi, test değişkeninin double tipinde, strtofloat(abc) fonksiyonunun dönüşü Extended tipinde oluşu. Bu iki farklı tipi birbirine aktarmak hatalı işlemdir.

- Önce test := strtofloat(abc); deyip, yani asıl veriyi bozduktan sonra if ile karşılaştırmaya tabi tutuyorsunuz. :!:

- Ben de ısrarla aktarma işleminin aynı tipte değişken <-> fonksiyon sonuç ataması olması gerektiğinin altını tekrar tekrar çiziyorum.

- Bir de şunu deneyin o zaman... test değişkeninin tipini olması gereken tip olan extended yapın.

- Bir önceki mesajımda FormatFloat fonksiyonunun EXTENDED tip döndürdüğünü söylemiş olmama rağmen neden halen DOUBLE tipinde olan test değişkenine Extended sonuç döndüren FormatFloat fonksiyonu ile değer aktarıyorsunuz ve bundan yola çıkarak yapılan karşılaştırmanın tutarsızlığına bakıyorsunuz, buna mana veremiyorum.
Resim
Resim ....Resim
Hakan Can
Üye
Mesajlar: 634
Kayıt: 04 Mar 2005 04:27
Konum: Ankara

Mesaj gönderen Hakan Can »

mrmarman yazdı:- Evet aslında şimdi birşeyin farkına vardım. O da hatanın ne olduğunu henüz algılamamış olmanız... :oops:

- Ben mi ifade edemiyorum yoksa görmek o kadar zor mu ? Önce değişkenler arası hatalı aktarım yapıyorsunuz, sonra bu hatalı sonuçla olması gerekeni karşılaştırma yapıp bana soruyu yineliyorsunuz..

- Verdiğiniz kod bloğunda ve nicelerinde sorun ne idi, test değişkeninin double tipinde, strtofloat(abc) fonksiyonunun dönüşü Extended tipinde oluşu. Bu iki farklı tipi birbirine aktarmak hatalı işlemdir.

- Önce test := strtofloat(abc); deyip, yani asıl veriyi bozduktan sonra if ile karşılaştırmaya tabi tutuyorsunuz. :!:

- Ben de ısrarla aktarma işleminin aynı tipte değişken <-> fonksiyon sonuç ataması olması gerektiğinin altını tekrar tekrar çiziyorum.

- Bir de şunu deneyin o zaman... test değişkeninin tipini olması gereken tip olan extended yapın.

- Bir önceki mesajımda FormatFloat fonksiyonunun EXTENDED tip döndürdüğünü söylemiş olmama rağmen neden halen DOUBLE tipinde olan test değişkenine Extended sonuç döndüren FormatFloat fonksiyonu ile değer aktarıyorsunuz ve bundan yola çıkarak yapılan karşılaştırmanın tutarsızlığına bakıyorsunuz, buna mana veremiyorum.
Hocam benim dediklerim aynen geçerli. Sizin dediğinizi ta başından beri doğru algıladım ama maalesef benim vurgulamak istediğimi siz algılayamadınız.

Şimdi ben size soruyorum:

1. Double Delphi'nin belkide en çok kullanılan gerçek sayı değişken tipi. Ben şimdi bu tipe alfasayısal bir değişken atamak istediğimde StrToFloat yerine ne kullanacağım?

2. Diyelim ki ben vazgeçtim Double kullanmaktan yerine Extended kullanıyorum peki Veritabanı işlemlerinde sayısal alanlar için AsFloat kullanıyoruz ve bu Double tipinde ve benzer bir işlemi yaptığınızda yine aynı hata ile karşılaşacaksınız ve bu durumda ne yapacaksınız?

Hem atamalarda aynı tip kullanılacak diye bir kural yok ki. Yani bu Pascal'dan beri böyle. Hem niye Double değişkene Extended atanmasın ki? Küsüratını atar ve atamasını yapar. Zaten mantıksız olsa derlerken hata mesajı verir. Sonuçta böyle bir atama mantıksız değil.

Ben bu problemle defaaten karşılaştım ve farklı çözüm şekilleri geliştirmek zorunda kaldım.

Sonuçta problem Extended veya Double tip olayı değil. Gerçek sayılarla ilgili işlemlerde Delphi beklenenden farklı sonuçlar üretebiliyor (gerçi bir kısmı mantıklı).

Neden olarak da ben kendi kodlarını incelediğimde bazı yerlerde ASM kullanması olduğu kanaatine varmıştım.

İyi çalışmalar.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@Hakan Can yazdı:Sonuçta problem Extended veya Double tip olayı değil. Gerçek sayılarla ilgili işlemlerde Delphi beklenenden farklı sonuçlar üretebiliyor (gerçi bir kısmı mantıklı).

@Hakan Can yazdı:Hem atamalarda aynı tip kullanılacak diye bir kural yok ki. Yani bu Pascal'dan beri böyle. Hem niye Double değişkene Extended atanmasın ki? Küsüratını atar ve atamasını yapar. Zaten mantıksız olsa derlerken hata mesajı verir. Sonuçta böyle bir atama mantıksız değil.


- Bunlara katılmıyorum. Kral olmaz mı, kesin kurallar vardır. Küsüratı atar diye birşey de yok. Fonksiyon için kurallar ve istisnalar vardır. Kuralda/istisnada ne varsa fonksiyon onu yapar. Bu operasyondur. Type özellikleri ise operasyon değildir. Ürünün kendisidir. Karıştırmayalım.

- Şunu düşünün bir çok dil ve bir çok tip tanımlaması var. Neden ?

- Delphi de tümü gibi bu tüm diller için uygun bir platform olmak için çabalayan bir programlama dili. Yoksa üç tane tip tanımı yeter idi. Float, Integer, String...

- Zorunlu olunan nokta şu :

- Bir fonksiyon tanımlarken ürün type ne ise seçmek. StrToFloat fonksiyonunu üretenler ise Extended tipini seçmiş. Siz de bir tane fonksiyon yazın çok basittir bilirsiniz, StrToDouble olsun... Buna imkan her zaman var...

- Burada floating point bir rakamı irdelemiyoruz. Bu rakamı hangi ortamda tutacağımızı irdeliyoruz. Ortamlar eşit şartlarda olmalı ki kesip biçme atma gibi derleyicinin insafına kalmasın :lol: kontrol altında olsun.

- StrToFloat fonksiyonunu kullanacaksanız -ki dikkat ettiyseniz bir çok fonksiyon Extended kullanır- Siz de Extended kullanacaksınız. Diğer tüm fonksiyonlarda olduğu gibi, her type tanımının lazım olduğu yer farklı.

- Sözün özü, hesaplamalarda Double tipi kullanmayın.. Aşağıda Delphi Help'den bir alıntıyı yazıyorum. Bunları bilelim, uyumlu kullanalım...

Kod: Tümünü seç

Fundamental real types
Type        Range                           Significant digits   Size in bytes
Real48      2.9 x 10^-39   .. 1.7 x 10^38   11-12                6
Single      1.5 x 10^-45   .. 3.4 x 10^38    7-8                 4
Double      5.0 x 10^-324  .. 1.7 x 10^308  15-16                8
Extended    3.6 x 10^-4951 .. 1.1 x 10^4932 19-20                10
Comp        -2^63+1 .. 2^63 -1              19-20                8
Currency	-922337203685477.5808..          19-20                8
                922337203685477.5807

Generic real types
Type       Range                            Significant digits   Size in bytes
Real       5.0 x 10^-324 .. 1.7 x 10^308    15-16                8
Resim
Resim ....Resim
Cevapla