Konuyu Oyla:
  • Derecelendirme: 0/5 - 0 oy
  • 1
  • 2
  • 3
  • 4
  • 5
matematiksel karşılaştırma hatası
#1
unit Unit1;

interface

uses
 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Mask, Vcl.Buttons, Vcl.NumberBox;

type
 TForm1 = class(TForm)
   BitBtn1: TBitBtn;
   NumberBox1: TNumberBox;
   procedure BitBtn1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
   function kontrol(dval: double): string;
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
NumberBox1.Value := 2.40;
showmessage( kontrol(NumberBox1.Value) );
end;

function TForm1.kontrol(dval: double): string;
begin
 if (dval < 2.40) then result := 'Küçük'
 else
   result := 'Küçük Değil';
end;

end.

Bu işlemin sonucu nasıl oluyor da 'Küçük' dönüyor anlamış değilim, yardımcı olabilecek varsa sevineceğim.
Cevapla
#2
Muhtemelen "NumberBox1" tam sayı bir değer alabiliyor. NumberBox1'in sayı tipini kontrol edin.
Numberbox1'in Properties'inde "MODE" diye bir ayar var. Bunu Currency'yapmanız lazım.
Cevapla
#3
(09-03-2026, Saat: 17:35)enigma Adlı Kullanıcıdan Alıntı: Muhtemelen "NumberBox1" tam sayı bir değer alabiliyor. NumberBox1'in sayı tipini kontrol edin.
Numberbox1'in Properties'inde "MODE" diye bir ayar var. Bunu Currency'yapmanız lazım.

Onu da denedim yine aynı oldu, Numberboxın döndürdüğü sayı tipi Extended , fonksiyon da tanımladığım veri tipi double, bu yüzden sıkıntı oluyor, Extended tanımlayınca onu da sorun çıkartmadı bu "Double" küsüratlı işlemlerde sorunlu bir veri tipi sanırım Sad
Cevapla
#4
bende de döviz kur çevriminde aynı sorunla karşılaşmıştım. sorun Double içeirğin ikili sayı düzeninde saklanırken küsürata düşmesi. Hassasiyet sorunu yani.
Ben de kontrolü kendi elime alınca çözmüştüm. önce 6 haneli 1 ile çarptım sonra ROUND ile yuvarlayıp küsuratı sabitledikten sonra çarptığım aynı sayıya bölüp . İşlemi tersine almak gibi yani. 

Eğer noktadan sonra 6 tane haneniz zaten varsa, bu durumda 1E12 ile çarpın ve 1E12'ye geri bölün ki hassasiyet son 6 haneye kadar sorunsuz işlesin.

function FloatDeger(Value: Double): Double;
begin
 Result := Round(Value * 1E6) / 1E6;
end;

function TForm1.kontrol(dval: double): string;
begin
if ( FloatDeger(dval) < FloatDeger(2.40) )
 then begin
   result := 'Küçük'
 end
 else
   result := 'Küçük Değil';
end;
Saygılarımla
Muharrem ARMAN

guplouajuixjzfm15eqb.gif
Cevapla
#5
@mrmarman  bey teknik açıklamasını yaptı. Yapay zekaya sorup herkesin öğrenebileceği bir şeyi, hem konuya katkı sağlamak hemde konuyu okumak için buraya kadar gelenlerin işini kolaylaştırmak için AI cevabını buraya ekliyorum.

//----Yapay zeka cevabı----------

Bu durum, bilgisayar bilimlerinde "Floating Point Precision" (Kayan Noktalı Sayı Hassasiyeti) olarak bilinen çok yaygın ve can sıkıcı bir durumdur. Görünüşte 2.40 olan bir sayı, bellekte tam olarak 2.40 olarak saklanamayabilir.

Sorunun Nedeni
Bilgisayarlar sayıları ikilik (binary) sistemde saklar. Bazı ondalıklı sayılar (0.1, 0.4, 2.4 gibi) ikilik sistemde sonsuz bir devirli sayıya dönüşür.

Senin örneğinde:
  • NumberBox1.Value(Double) tam olarak 2.4000000000000000 yerine 2.3999999999999999 gibi çok küçük bir farkla saklanıyor olabilir.
  • if (dval < 2.40) kontrolü yaptığında, sağ taraftaki 2.40 sabiti de derleyici tarafından farklı bir hassasiyetle ele alınabilir.
  • Sonuçta 2.3999... < 2.40 ifadesi doğru (True) kabul edilir ve "Küçük" sonucunu alırsın.
Çözüm Yolları
Bu sorunu çözmek için Delphi'de (ve genel programlamada) üç temel yaklaşım vardır:

1.SameValue Fonksiyonunu Kullanmak (En Doğru Yol)
Delphi'nin System.Math kütüphanesinde bulunan SameValue fonksiyonu, iki ondalıklı sayının "yeterince yakın" olup olmadığını kontrol eder.

uses
 System.Math; // Bunu interface veya implementation kısmına eklemelisin.

function TForm1.kontrol(dval: double): string;
begin
 // Epsilon (hata payı) kullanarak karşılaştırma yapar
 if SameValue(dval, 2.40, 0.0001) or (dval > 2.40) then
   result := 'Küçük Değil'
 else
   result := 'Küçük';
end;

2. Sayıyı Tam Sayıya Çevirerek Karşılaştırmak
Eğer virgülden sonraki basamak sayın belliyse (örneğin 2 basamak), her iki tarafı da 100 ile çarpıp tam sayıya (Integer) çevirerek karşılaştırabilirsin.

function TForm1.kontrol(dval: double): string;
begin
 // 2.40 -> 240 olur. Hassasiyet sorunu ortadan kalkar.
 if Trunc(dval * 100) < Trunc(2.40 * 100) then
   result := 'Küçük'
 else
   result := 'Küçük Değil';
end;

3. Currency Veri Tipini Kullanmak
Eğer finansal bir hesaplama yapıyorsan, Delphi'de Double yerine Currency tipini kullanmanı öneririm. Currency tipi arka planda tam sayı olarak tutulur ve bu tür kayan nokta hatalarına neden olmaz.

function TForm1.kontrol(dval: Currency): string; // Parametreyi Currency yap
begin
 if (dval < 2.40) then 
   result := 'Küçük'
 else
   result := 'Küçük Değil';
end;
Cevapla
#6
(10-03-2026, Saat: 10:18)frmman Adlı Kullanıcıdan Alıntı: @mrmarman  bey teknik açıklamasını yaptı. Yapay zekaya sorup herkesin öğrenebileceği bir şeyi, hem konuya katkı sağlamak hemde konuyu okumak için buraya kadar gelenlerin işini kolaylaştırmak için AI cevabını buraya ekliyorum.

//----Yapay zeka cevabı----------

Bu durum, bilgisayar bilimlerinde "Floating Point Precision" (Kayan Noktalı Sayı Hassasiyeti) olarak bilinen çok yaygın ve can sıkıcı bir durumdur. Görünüşte 2.40 olan bir sayı, bellekte tam olarak 2.40 olarak saklanamayabilir.

Sorunun Nedeni
Bilgisayarlar sayıları ikilik (binary) sistemde saklar. Bazı ondalıklı sayılar (0.1, 0.4, 2.4 gibi) ikilik sistemde sonsuz bir devirli sayıya dönüşür.

Senin örneğinde:
  • NumberBox1.Value(Double) tam olarak 2.4000000000000000 yerine 2.3999999999999999 gibi çok küçük bir farkla saklanıyor olabilir.
  • if (dval < 2.40) kontrolü yaptığında, sağ taraftaki 2.40 sabiti de derleyici tarafından farklı bir hassasiyetle ele alınabilir.
  • Sonuçta 2.3999... < 2.40 ifadesi doğru (True) kabul edilir ve "Küçük" sonucunu alırsın.
Çözüm Yolları
Bu sorunu çözmek için Delphi'de (ve genel programlamada) üç temel yaklaşım vardır:

1.SameValue Fonksiyonunu Kullanmak (En Doğru Yol)
Delphi'nin System.Math kütüphanesinde bulunan SameValue fonksiyonu, iki ondalıklı sayının "yeterince yakın" olup olmadığını kontrol eder.

uses
 System.Math; // Bunu interface veya implementation kısmına eklemelisin.

function TForm1.kontrol(dval: double): string;
begin
 // Epsilon (hata payı) kullanarak karşılaştırma yapar
 if SameValue(dval, 2.40, 0.0001) or (dval > 2.40) then
   result := 'Küçük Değil'
 else
   result := 'Küçük';
end;

2. Sayıyı Tam Sayıya Çevirerek Karşılaştırmak
Eğer virgülden sonraki basamak sayın belliyse (örneğin 2 basamak), her iki tarafı da 100 ile çarpıp tam sayıya (Integer) çevirerek karşılaştırabilirsin.

function TForm1.kontrol(dval: double): string;
begin
 // 2.40 -> 240 olur. Hassasiyet sorunu ortadan kalkar.
 if Trunc(dval * 100) < Trunc(2.40 * 100) then
   result := 'Küçük'
 else
   result := 'Küçük Değil';
end;

3. Currency Veri Tipini Kullanmak
Eğer finansal bir hesaplama yapıyorsan, Delphi'de Double yerine Currency tipini kullanmanı öneririm. Currency tipi arka planda tam sayı olarak tutulur ve bu tür kayan nokta hatalarına neden olmaz.

function TForm1.kontrol(dval: Currency): string; // Parametreyi Currency yap
begin
 if (dval < 2.40) then 
   result := 'Küçük'
 else
   result := 'Küçük Değil';
end;

Currency ondalık hane sayısını 4 haneye kadar tutuyor. Bunu dikkate alarak kullanılmalı. Daha hassas 6 hane gibi rakamlar için bu yetersiz olacaktır.
PostgreSQL - Linux - Delphi, Poliüretan
WWW
Cevapla
#7
Yanıt veren yorum yapan herkese çok teşekkür ederim çok faydalı oldu.
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Delphi ile SQL server bağlantı hatası yakalama Under 20 1.940 21-11-2025, Saat: 15:24
Son Yorum: mrmarman
  OpenSSL Hatası mcuyan 1 487 29-04-2025, Saat: 02:28
Son Yorum: mcuyan
Photo Delphi 12.2ilginç bir ide hatası tuna 13 3.368 25-03-2025, Saat: 09:47
Son Yorum: tuna
  Delphi Ide hatası Bay_Y 6 1.229 04-02-2025, Saat: 10:56
Son Yorum: Bay_Y
  wsdl veri çekme hatası tuna 6 1.344 15-01-2025, Saat: 16:54
Son Yorum: hi_selamlar



Konuyu Okuyanlar: 1 Ziyaretçi