yuvarlama
y.kulac12.04.2005 - 15:33:34
s.a.
öncelikle ytl ve yuvarlama ilel ilgili forumumuzda çok düküman buldum ve hepsini inceledim.
ama sorunumu halledemedim.
firbird veritanbanı ve ibx bilşenlerini kullanıyorum.
veritabanında kullandığım alan float. hesaplama işlemini direk value üzerinden yaptırıyorum. displayformat özelliğinide ##0.00 olarak ayarladım

ibdataset1tabanaylık.value:= ibtable1tabanaylık.value*1000;

herşey normal sonuç 50,1252555 gibi çıkıyor. virgülden sonraki 3.sayı 5 olduğu için
normal olarak sonuç 50,12 oluyor. ama program gereği virgülden sonraki
3. sayı 5 ve üzeri ise 2.sayı bir üste yuvarlanmak zorunda 4 ve altı ise aşağı yuvarlanmak zorunda.
yani 50,125 = 50,13 75,245 = 75,25 olmalı
soru biraz uzun oldu kusura bakmayın.
neler önerirsiniz.
iyi çalışmalar.
 
coderlord12.04.2005 - 16:27:23

uses Math;
...
...
...
...
initialization
SetRoundMode( .. ); // rmNearest, rmDown, rmUp, rmTruncate
end.


Unit'ine şekildeki gibi initialization bölümü ekleyip rmNearest... vs. parametrelerini tek tek dener misin?

Bir de yuvarlama işlemini sen nasıl yapıyorsun? 1000 ile neden çarptın?

bkz. RoundTo function.
 
y.kulac12.04.2005 - 16:41:19
1000 ile çarpımın yuvarlama ile ilgisi yok.o tabanaylık hesaplanmasına kullanılıyor. ayrıca ben yuvarlama yapmıyorum. ama yapmam gerek. . aryıca "rmNearest... vs. parametrelerini" anlamadım. açıklarsanız sevinirim.
iyi çalışmalar.
 
coderlord12.04.2005 - 17:08:20
rmNearest en yakın değere, rmUp yukarı rmDown aşağı yuvarlar. Programında bir dene bu parametreleri. Mesela rmUp yap.
 
y.kulac13.04.2005 - 09:14:30
hocam maalesef olmadı round fonsiyonu en yakın tam sayıya yuvarlama yapıyor. ama benim alanlar float tipinde.
kolay gelsin
 
t-hex13.04.2005 - 10:52:19
Merhaba,
O zaman sizde yuvarlatmadan önce 0.001 ekletin sayıya, o zaman istediğiniz olur. Nede olsa sizin için gerekli olan ondalık sadece 2 basamak.
 
highmemo13.04.2005 - 11:10:26
Selam,

sana elimdeki fonksiyonu vereyim.


function myFixPoint(Value: Double; DecCount: Integer): Double ;
begin
Result := StrToFloat( Format('%.*f', [DecCount, StrToFloat(FloatToStr(Value))]) );
end;


Sakın şaşırma :
"StrToFloat(FloatToStr " böyle bir yapı kullanmamın sebebi
örneğin programda 24 diye gördüğünüz sayı aslında 23.9999 vs gidiyor.. Bu konuyu bazı arkadaşlarımız biliyor. Eğer bu şekilde kullanmazsam çok ender zamanlarda ondalıklarda hata oluşturuyor.. Şimdi örnek veremiyorum ama işini Çözer..

Kullanım Örneği
myFixPoint( IBDatasetTUTAR.asFloat * 1000, 2);
 
y.kulac13.04.2005 - 13:42:10
teşekkür ederim arkadaşlar.

sorunu halletim. t-hex kardeşimin yolunu uyguladım. sonuca 0.001 ekledim
diğer arkadaşlara da teşekkür ederim.
aslında bazı sorunlar o kadar basit ki ama insanın aklına gelmiyor.
herkese iyi çalışmalar.
 
hdayi13.04.2005 - 13:50:48
Sonuca 0.001 eklemek hatalı bir sonuca götürebilir seni.
Ben şöyle bir kod yazmıştım tl'yi ytl'ye çevirirken
Edit2.Text:=FloatToStrF((StrToFloat(Edit1.Text')/1000000),ffNumber,30,2);


Hiç bir problem olmamıştı.
 
t-hex13.04.2005 - 14:18:32
Merhaba,
sonuca 0.001 eklemek sadece 2 haneli küsurat gerektirdiğinde yanlış sonuca götürmüyor. 3. hanenin 9 olması durumda zaten bir üste tamamlanmış oluyor, 3. hanenin 0 olması durumda da arkadaşın yaşadığı sorun ortadan kalkıyor.

Tabi bu sadece pratik bir çözüm, her şey yapılması gerektiği gibi yapılmalı
 
hdayi13.04.2005 - 14:44:48
3. hanenin 4 olması durumunda hataya götürür bu sonuç.
3.234=3.23
3.234+0.001=3.235=3.24<>3.23
 
coderlord13.04.2005 - 15:14:02
Problemin kaynağı ve sorunun çözümü için bir link.

http://www.festra.com/eng/tip-rounding.htm

Özetle olay şu. Delphi ta Borland Pascal zamanından gelen bir yuvarlama algoritması kullanmakta. Buna bankers rounding algoritması diyorlar.

Bu algoritma şöyle çalışıyor:

- Tam sayı kısmı tek sayı ise ve ondalıklı kısım 0.5 ise bir üst tam sayıya yuvarlıyor. (Bu bizim istediğimiz)

- Tam sayı kısmı çift ve ondalıklı kısım 0.5 ise aşağıya yuvarlıyor. (İstenmeyen)

Bu bir hata falan değil. Algoritmanın yapısından kaynaklanıyor.

Gönderdiğim SetRoundMode func'u ile bunu istediğimiz hale getirmek aslında mümkün. Arkadaşınki nasıl gelmemiş anlamadım.
 
y.kulac13.04.2005 - 16:06:58
arkadaşlar
yuvarlama yapmadan dahi 12.255 sonucu zaten 12.25 oluyor (displayformat özelliğini ###,##0.00 yapınca)
ama memur maaşı hazırlanırken muhasebe müdürlüğünün talimatı gereği kuruşlu hanelerde virgülden sonraki 3. hane 5 ve üzeri ise 2.hane yukarı, 4 ten aşağı ise aşağı yuvarlanması gerekiyor. bu istisnai bir durum.
coderlord kardeşimin verdiği linkteki fonsiyonu şu şekilde değiştirdim

function RoundCorrect(R: Real): currency;
begin
Result:= trunc(R); // extract the integer part
if Frac(R) >= 0.005 then // if fractional part >= 0.5 then...
Result:= Result + 0.001; // ...add 1
end;

ama sonuç 25.245 = 25.00 oluyor.
hayırlı işler kolay gelsin.
 
oguzozturk7413.04.2005 - 20:54:05
Fahrettin Abi demiş ki :
------------------------------------------

Aslında round fonksiyonu doğru çalışıyor. Fakat aldığımız matematik eğitimi dolayısıyla Round fonksiyonunun çalışma mantığını yanlış tahmin ediyoruz...

Şöyle ki Round fonksiyonu normalde en yakın tam sayıya yuvarlama yapar fakat eğer yuvarlayacağınız rakam tam olarak ortada ise yani 2.5 3.5 gibi rakamlar ise o zaman en yakın çift rakama yuvarlama yapmaktadir.

Yani
round(2.5)=2
round(3.5)=4
sonuçları gayet normaldir. Sorun hepimizin başına gelen bu fonksiyonun çalışma şeklini yanlış tahmin etmemizdir. Helpten baktığınızda şu cümleyi görmektesiniz zaten.
X is a real-type expression. Round returns an Int64 value that is the value of X rounded to the nearest whole number. If X is exactly halfway between two whole numbers, the result is always the even number.

Peki çözüm ne derseniz de ya Round fonksiyonunun bu maktığını bilerek kullanın ya da 2.5 yuvarlanınca 3 olsun diyorsaniz. RoundX isimli su fonksiyonu tanimlyip kullanın.

function RoundX( x : Extended ) : Extended;
var
Rint, Rdec : Extended;
begin
Rint := int(x);
Rdec := x - Rint ;
If Rdec >= 0.5 then
Result := Rint + 1
else
Result := Rint;
end;
 
fahrettin14.04.2005 - 07:39:56
Evet demiştim hakikaten.... :)
 
tsamim03.05.2005 - 19:58:56
merhaba arkadaşlar ;

Bu msg yuvarlamayla ilgili buraya yeni bakacak arkadaşlar için yazıyorum.

Bende ytl olayında yani yarım kuruş olayında takılmıştım birde ytl rakamlarımın database'de (benim vt firebird double alanlardan bahsediyorum) ondalık kısmının 2 haneden fazla olmasını istemiyordum.

diğer örneklere göre highmemo arkadaşın verdiği fonksiyon çok daha kolay ve direk sonuca gidiyor diye düşünüyorum yeni bakacak arkadaşların dikkatine......
 
celalatak04.05.2005 - 13:26:02
Matematikte yuvarlama kuralı 0,5 ile toplayıp küsurat kısmını atmaktır. Yani

1,4+0,5=1,9 oda yuvarlanırsa 1 olur.
Benzer şekilde 1,6+0,5=2,1 yuvarlama ile 2 bulursunuz.

Delphide aşağıdaki gibi kullanabilirsiniz.




floor(sayi+0.5)


Eğer para birimide kuruşlarda yuvarlama yapmak istiyorsanız


floor(para*100+0.5)/100;


0,01 ile toplarsanız hataya yol açabilir
 
t-hex04.05.2005 - 14:29:40
Merhaba,

Neyse, şimdi arkadaşlar 0,001 ile toplama olayını yanlış anlıyorsunuz. Bu öneri benden çıktığı için açıklama yapmak istiyorum. Twisted Evil

Arkadaş sorusunda 1,965 gibi bir sayıyı yuvarlatmak istediğinde sayının 1,97 olması gerekirken 1,96 olarak kaldığını bunu nasıl aşacağını sordu.

Eğer işlemin bu şekilde gerçekleştiğini göz önünde bulundurursanız 0,001 ekletmenin her zaman doğru sonuç verdiğini görürsünüz. (Ben hata yaptırdığı bir örnek düşünemedim daha)

Ama daha sonradan Delphideki yuvarlamanın "Banker's Rounding" olduğu anlaşıldığı için 0,001 ekletmek hatalı sonuç verdiyor çünkü en yakın çift sayıya yuvarlanıyor.

Olay bundan ibarettir.

Kolay gelsin.
 
NOT : Bu sayfa google'un siteyi indekslemesi içindir. www.delphiturkiye.com/forum/ adresini kullanınız!
1998-2006 www.delphiturkiye.com