it-swarm-tr.com

Muhasebe Uygulama Dolar Tutarı için Float veya Ondalık Kullanılır

Eski Muhasebe Sistemimizi VB.NET ve SQL Server'da yeniden yazıyoruz. Yeniden yazmak için yeni bir .NET/SQL Programcı ekibi takımı getirdik. Sistemin çoğu, Floats kullanarak Dolar miktarlarıyla zaten tamamlandı. Programladığım eski sistem dili bir Float'a sahip değildi, bu yüzden muhtemelen bir Ondalık kullanırdım.

Tavsiyen nedir

Float veya Ondalık veri türü dolar miktarları için kullanılmalı mıdır?

Bazı lehte ve aleyhte olanlar nelerdir?

Günlük işimizde bahsettiğimiz bir Con, iki ondalık basamağın üstünde bir sonuç veren bir miktar hesaplarken dikkatli olmanız gerekiyordu. Tutarı iki ondalık basamağa yuvarlamak zorunda kalacaksınız.

Başka bir Con ise tüm ekranlardır ve yazdırılan miktarların iki ondalık pozisyon gösteren bir Format Beyanı olması gerekir. Bunun yapılmadığını ve miktarların doğru görünmediğini birkaç kez fark ettim. (yani, 10.2 veya 10.2546)

Bir profesyonel, Float'ın Ondalık 9 byte alacağı diskte yalnızca 8 bayt alır (Ondalık 12,2) 

74
Gerhard Weiss

Float veya Ondalık veri türü dolar miktarları için kullanılmalı mıdır?

Cevap kolaydır. Asla yüzemezsin. ASLA !

Şamandıralar IEEE 754 daima ikilik, sadece yeni standart IEEE 754R tanımlanmış ondalık formatlara göredir. Kesirli ikili bölümlerin çoğu, tam ondalık gösterimi hiçbir zaman eşitleyemez.
Herhangi bir ikili sayı, m/2^n (m, n pozitif tamsayılar), herhangi bir ondalık sayı m/(2^n*5^n) olarak yazılabilir.
İkili dosyalar birincil factor 5 dosyasından yoksun olduğundan, tüm ikili sayılar tam olarak ondalık sayılarla gösterilebilir, ancak bunun tersi de geçerli değildir.

0.3 = 3/(2^1 * 5^1) = 0.3

0.3 = [0.25/0.5] [0.25/0.375] [0.25/3.125] [0.2825/3.125]

          1/4         1/8         1/16          1/32

Böylece verilen sayıdan daha yüksek veya daha küçük bir sayı elde edersiniz. Her zaman.

Bu neden önemli? Yuvarlama.
Normal yuvarlama, 0..4 aşağı, 5..9 yukarı anlamına gelir. Bu yüzden, mu sonucunun Olup olmadığını ya da 0.049999999999.... ya da 0.0500000000... önemli olup olmadığını anlarsınız. Bunun 5 cent olduğunu biliyor olabilirsiniz, ancak bilgisayar bunu bilmez ve 0.4999 turlarını yuvarlar. (yanlış) ve 0.5000... yukarı (sağ).
Kayan nokta hesaplamaları sonucu her zaman küçük hata terimleri içerdiğinden, karar tamamen şanslıdır. Ondalık çift-sayılarla ikili sayılarla işlem yapmak istiyorsanız, umutsuzlaşır.

İkna olmamış mı? Hesap sisteminizde her şeyin tamamen iyi olduğu konusunda ısrar ediyorsunuz?
Varlık ve borçlar eşit mi? Tamam, sonra her girişin verilen biçimlendirilmiş sayılarının her birini alın, bunları ayrıştırın ve bağımsız bir ondalık sistemle toplayın! Biçimlendirilmiş toplamla karşılaştırın.
Hata, yanlış bir şey var, değil mi? 

Bu hesaplama için, aşırı doğruluk ve sadakat gerekiyordu (Oracle'ın FLOAT'ı kullandık), böylece "bir kuruşun milyarda'sını" kaydedildiğini kaydedebildik.

Bu hataya karşı yardımcı olmuyor. Çünkü tüm insanlar otomatik olarak bilgisayarın doğru şekilde toplandığını varsayıyorlar, pratikte kimse bağımsız olarak kontrol etmiyor.

105
TSK
41
Nakilon

Öncelikle şunu okumalısınız Her Bilgisayar Bilimcisi Kayan Nokta Aritmetiği Hakkında Bilmeniz Gerekenler . O zaman gerçekten bir tür sabit nokta/rasgele kesinlikli sayı paketi (örneğin, Java BigNum, python ondalık modül) kullanmayı düşünmelisiniz, aksi halde bir incinme dünyasında olacaksınız. Daha sonra yerel SQL ondalık tipini kullanmanın yeterli olup olmadığını anlayın. 

Artık oldukça eski olan hızlı x87 fp'yi göstermek için yüzer/çiftler var (ed). Hesaplamaların doğruluğunu önemsiyorsanız ve/veya sınırlamalarını tamamen karşılamıyorsanız, bunları kullanmayın.

22
Rich Schuler

Ek bir uyarı olarak, SQL Server ve .Net çerçevesi yuvarlama için farklı bir varsayılan algoritma kullanır. Math.Round () içindeki MidPointRounding parametresini kontrol ettiğinizden emin olun. Net framework varsayılan olarak Bankacılar algoritmasını kullanır ve SQL Server Simetrik Algoritmik Yuvarlamayı kullanır. Wikipedia makalesine göz atın here

10
Darrel Miller

Muhasebecilerinize sorun! Şamandıra kullandığınız için size kaşlarını çatıyorlar. Daha önce yayınlananlardan bir tanesi gibi, doğrulukla ilgilenmiyorsanız SADECE kayan nokta kullanın. Her ne kadar para söz konusu olduğunda buna karşı olacağım.

Muhasebe yazılımında bir şamandıra kabul DEĞİLDİR. 4 ondalık basamakla ondalık kullanın.

7
Ricardo C

Kayan noktalarda beklenmeyen irrasyonel sayılar var.

Mesela 1/3 ondalık olarak saklayamazsınız, 0.3333333333 ... olur (ve benzeri)

Şamandıralar aslında bir ikili değer ve 2 üslü bir güç olarak saklanır.

Yani 1.5 -1'e 3 x 2 olarak depolanır (veya 3/2)

Bu 2 temel üslerin kullanılması, örneğin bazı irrasyonel sayılar yaratır:

1.1'i bir kayan noktaya dönüştürün ve ardından tekrar geri dönüştürün, sonuç şöyle olacaktır: 1.0999999999989

Bunun nedeni, 1.1'in ikili gösteriminin aslında 154811237190861 x 2 ^ -47 olması, bir çift kutunun işleyebileceğinden daha fazla olmasıdır.

Bu konuda daha fazla blogumda , ancak temelde, depolama için, onluklarla daha iyi durumdasınız.

Microsoft SQL sunucusunda money veri türüne sahipsiniz - bu genellikle finansal depolama için en iyisidir. 4 ondalık pozisyon için doğrudur.

Hesaplamalar için daha fazla sorun yaşarsınız - yanlışlık küçük bir kesirdir, ancak bunu bir güç işlevine sokun ve hızlı bir şekilde belirginleşir. 

Bununla birlikte, ondalık sayılar hiçbir matematik türü için çok iyi değildir - örneğin ondalık güçler için yerel destek yoktur.

6
Keith

Burada biraz arka plan ....

Hiçbir sayı sistemi tüm gerçek sayıları tam olarak idare edemez. Hepsinin kendi sınırlamaları vardır ve bu hem standart IEEE kayan nokta hem de imzalı ondalık içerir. IEEE kayan nokta kullanılan bit başına daha hassastır, ancak burada önemi yoktur.

Mali rakamlar, ilgili sözleşmelerle birlikte yüzyıllarca süren kağıt kalem uygulamasına dayanmaktadır. Makul olarak doğrular, ancak daha da önemlisi, tekrarlanabilirler. Çeşitli sayılar ve oranlarla çalışan iki muhasebeci aynı numara ile gelmelidir. Uyuşmazlık için herhangi bir yer dolandırıcılık için yer var.

Bu nedenle, finansal hesaplamalar için doğru cevap, aritmetikte iyi olan bir EBM ile aynı cevabı veren her şeydir. Bu ondalık aritmetik, IEEE kayan nokta değil.

5
David Thornley

SQL sunucusunun ondalık türünü kullanın.

Para veya kayan nokta kullanmayın.

para 4 ondalık basamak kullanır, ondalık KULLANMAKTAN DAHA HIZLIDIR, ANCAK bazı belirgin ve bazıları ise yuvarlama ile ilgili açık olmayan sorunlardan muzdariptir ( bu bağlantı sorununa bakın

5
Mitch Wheat

Tavsiye ettiğim şey, her şeyi sentlerde depolayan 64 bit tam sayıları kullanmak.

5
Joshua

Şamandıralar tam gösterimler değildir, örneğin çok büyük ve çok küçük değerler eklerken hassas konular mümkündür. Bu nedenle, kesin sayı yeterince nadir görünse de, ondalık türler para birimi için önerilir.

Açıklığa kavuşturmak için, ondalık sayı 12,2, bu 14 haneyi tam olarak saklayacaktır, oysa şamandıra dahili olarak ikili bir gösterimi kullandığı gibi olmayacaktır. Örneğin, 0.01 tam olarak bir kayan nokta sayısıyla gösterilemez - en yakın gösterim aslında 0.0099999998

4
Niall

Gelişmesine yardım ettiğim bir bankacılık sistemi için sistemin "faiz tahakkuk" kısmından sorumluydum. Her gün, kodum o gün bakiyeye ne kadar faiz tahakkuk ettiğini (kazanılan) hesapladı.

Bu hesaplama için, aşırı doğruluk ve sadakat gerekiyordu (Oracle'ın FLOAT'sini kullandık) böylece tahakkuk eden "bir kuruşun milyarda'sını" kaydedebiliyorduk.

Faizi "aktifleştirmek" söz konusu olduğunda (yani, faizin hesabınıza geri ödenmesi), miktar kuruşa yuvarlanmıştır. Hesap bakiyeleri için veri türü iki ondalık basamaktı. (Aslında birçok ondalık basamakta çalışabilen çok para birimli bir sistem olduğundan daha karmaşıktı - ama biz her zaman bu para biriminin "kuruşuna" yuvarladık). Evet - orada kayıp ve kazancın "kesirleri" var, ancak bilgisayar rakamları gerçekleştiğinde (para ödenmiş veya ödenmiş) her zaman GERÇEK para değerleri olmuştur.

Bu, muhasebecileri, denetçileri ve denetçileri memnun etti.

Yani, müşterilerinize danışın. Size bankacılık/muhasebe kurallarını ve uygulamalarını söyleyeceklerdir.

4
Guy

Float'ı para için kullanmanın tek nedeni, doğru cevapları önemsememenizdir. 

4
David Singer

Muhasebe sistemlerinde bilmeniz gereken bir diğer husus, hiç kimsenin masalara doğrudan erişmemesi gerektiğidir. Bu, muhasebe sistemine tüm erişimin saklı işlemlerden geçirilmesi gerektiği anlamına gelir. Bu sadece SQl enjeksiyon saldırılarını değil dolandırıcılığı önler. Dolandırıcılık yapmak isteyen bir iç kullanıcı, hiç bir zaman veritabanı tablolarındaki verileri doğrudan değiştirme olanağına sahip olmamalıdır. Bu, sisteminizde kritik bir iç kontrol. Gerçekten hoşnutsuz çalışanların veritabanınızın arka ucuna gitmesini ve çeklerini yazmaya başlamasını istiyor musunuz? Veya onay yetkisine sahip olmadıklarında yetkisiz bir satıcıya gider onayladıklarını mı? Tüm kuruluşunuzdaki yalnızca iki kişi finansal veritabanınızdaki, dba'nız ve yedeklemenizdeki verilere doğrudan erişebilmelidir. Çok sayıda dbasınız varsa, yalnızca ikisinin bu erişime sahip olması gerekir.

Bunu söylüyorum, çünkü programcılarınız bir muhasebe sisteminde şamandıra kullanıyorlarsa, muhtemelen iç kontrol fikrine tamamen aşina değillerdir ve programlama çabalarında dikkate almamışlardır.

3
HLGEM

Ondalık kullanmaktan daha iyidir, sadece düz eski tamsayılar (ya da belki bir tür bigint) kullanmaktır. Bu şekilde her zaman mümkün olan en yüksek doğruluğa sahip olursunuz, ancak hassasiyet belirtilebilir. Örneğin, 100 sayısı şöyle biçimlendirilmiş 1.00 anlamına gelebilir:

int cents = num % 100;
int dollars = (num - cents) / 100;
printf("%d.%02d", dollars, cents);

Daha fazla hassasiyete sahip olmak istiyorsanız, 100 değerini aşağıdaki gibi daha büyük bir değere değiştirebilirsiniz: 10 ^ n, burada n ondalık sayıdır.

3
Peter Stuifzand

100 fraksiyondan n/100, ki burada n 0 <= n ve n <100 olacak şekilde doğal bir sayıdır, sadece dördü kayan nokta sayıları olarak gösterilebilir. Bu C programının çıktısına bir göz atın:

#include <stdio.h>

int main()
{
    printf("Mapping 100 numbers between 0 and 1 ");
    printf("to their hexadecimal exponential form (HEF).\n");
    printf("Most of them do not equal their HEFs. That means ");
    printf("that their representations as floats ");
    printf("differ from their actual values.\n");
    double f = 0.01;
    int i;
    for (i = 0; i < 100; i++) {
        printf("%1.2f -> %a\n",f*i,f*i);
    }
    printf("Printing 128 'float-compatible' numbers ");
    printf("together with their HEFs for comparison.\n");
    f = 0x1p-7; // ==0.0071825
    for (i = 0; i < 0x80; i++) {
        printf("%1.7f -> %a\n",f*i,f*i);
    }
    return 0;
}
2
Lars Bohl

Net için her zaman Money türü gibi bir şeyler yazabilirsiniz.

Bu makaleye bir göz atın: CLR için bir para türü - Yazar bence mükemmel bir çalışma yaptı.

2
Tomer Pintel

Parasal değerleri depolamak için SQL'in para türünü kullanıyordum. Son zamanlarda, birkaç çevrimiçi ödeme sistemiyle çalışmak zorunda kaldım ve bazılarının parasal değerleri depolamak için tamsayı kullandığını fark ettim. Mevcut ve yeni projelerimde tamsayı kullanmaya başladım ve bu çözümden oldukça memnunum.

2
George

Para birimi değerleri için muhtemelen bir çeşit sabit nokta gösterimi kullanmak isteyeceksiniz. Ayrıca Bankanın yuvarlamasını da araştırmak isteyeceksiniz ("yarı yuvarlak bile" olarak da bilinir.) Olağan "yarı yarıya yukarı" yönteminde var olan önyargılardan kaçınır.

1
user6931

Dolar tutarlarını depolamak için para veri türünü kullanmayı düşündünüz mü?

Ondalıkın bir bayt daha almasıyla ilgili Con ile ilgili olarak, umursamadığımı söyleyebilirim. 1 milyon satırda sadece 1 MB daha kullanacaksınız ve depolama bugünlerde çok ucuz.

1
Espo

Ne yaparsanız yapın, yuvarlama hatalarına karşı dikkatli olmalısınız. Gösterdiğinizden daha yüksek bir hassasiyet derecesi kullanarak hesaplayın.

1
1800 INFORMATION

Muhasebecileriniz nasıl yuvarladığınızı kontrol etmek isteyeceklerdir. Şamandıranın kullanılması, genellikle yapmak istediğiniz şekilde değil (bunun yerine taban/tavan kullanın) FORMAT () türü bir ifadeyle sürekli yuvarlama yapacağınız anlamına gelir.

Float veya gerçek yerine kullanılması gereken para birimi veri türleriniz (para, küçük para) var. Ondalık saklamak (12,2), yuvarlama işlemlerinizi ortadan kaldıracak, ancak aynı zamanda orta dereceli adımlar sırasında bunları da ortadan kaldıracaktır - bu gerçekten finansal bir uygulamada istediğiniz şey değildir.

0
David T. Macknet

float ve decimal ne zaman kullanılacağını tanımlayan mükemmel bir makale. Şamandıra yaklaşık bir değer saklar ve ondalık tam bir değer depolar.

Özet olarak, para gibi kesin değerler ondalık kullanmalı ve bilimsel ölçümler gibi yaklaşık değerler şamandıra kullanmalıdır.

Burada hem yüzmenin hem de ondalık sayının hassaslığı kaybedebileceğini gösteren ilginç bir örnek. Bir tamsayı olmayan bir sayı ekleyip aynı sayıyı çıkarmak, ondalık saymazken kesinliği kaybetmekle sonuçlanır:

    DECLARE @Float1 float, @Float2 float, @Float3 float, @Float4 float; 
    SET @Float1 = 54; 
    SET @Float2 = 3.1; 
    SET @Float3 = 0 + @Float1 + @Float2; 
    SELECT @Float3 - @Float1 - @Float2 AS "Should be 0";

Should be 0 
---------------------- 
1.13797860024079E-15

Tamsayılı olmayan bir sayı ile çarparken ve aynı sayıya böldüğünüzde, ondalık sayılar kesilmeden hassasiyetini kaybeder.

DECLARE @Fixed1 decimal(8,4), @Fixed2 decimal(8,4), @Fixed3 decimal(8,4); 
SET @Fixed1 = 54; 
SET @Fixed2 = 0.03; 
SET @Fixed3 = 1 * @Fixed1 / @Fixed2; 
SELECT @Fixed3 / @Fixed1 * @Fixed2 AS "Should be 1";

Should be 1 
--------------------------------------- 
0.99999999999999900
0
BrokeMyLegBiking

Her zaman Ondalık kullanın. Float, yuvarlama sorunları nedeniyle size yanlış değerler verecektir.

0
Roel Vlemmings

Kayan nokta sayıları sadece / bazın negatif katlarının toplamı olan sayıları temsil eder - ikili kayan nokta için, tabii ki, bu iki.

İkili kayan noktalarda tam olarak gösterilebilen sadece dört ondalık kesir vardır: 0, 0.25, 0.5 ve 0.75. Diğer her şey bir yaklaşımdır, 0.3333 ... aynı şekilde ondalık aritmetikte 1/3 için bir yaklaşımdır.

Kayan nokta, sonucun ölçeğinin önemli olduğu hesaplamalar için iyi bir seçimdir. Bazı ondalık basamaklarda doğru olmaya çalıştığınız kötü bir seçimdir.

0
Mike Dimmick