SQL Server'da sayısal, kayan nokta ve ondalık sayı arasındaki fark


322

Arasındaki farklar nelerdir numeric, floatve decimalhangi durumlarda kullanılmalıdır datatypes ve?

Her türlü finansal işlem için (örneğin maaş alanı için) hangisi tercih edilir ve neden?


1
Yukarıdaki ondalık ve sayısal bağlantının docs.microsoft.com/en-us/sql/t-sql/data-types/… sürümüne güncellenmesi gerekiyor . Yukarıdaki bağlantı artık mevcut değil.
Nigel Ainscoe

1
Genellikle, finansal konularla uğraşırken , Kayan nokta olanlar dışında Tamsayı türleri ile çalışmak ilginçtir ve değerleri dolar yerine sent olarak saklar .
Pedro

Yanıtlar:


494

kullanmak yüzdürme ya da gerçek veri türleri sadece tarafından sağlanan hassas ondalık (38 basamak) yetersizse

  • Yaklaşık sayısal veri türleri , birçok sayı için belirtilen kesin değerleri depolamaz ; değerin son derece yakın bir yaklaşımını depolarlar ( Technet )

  • WHERE yan tümcesi arama koşullarında, özellikle = ve <> işleçlerinde ( Technet ) kayan nokta veya gerçek sütunlar kullanmaktan kaçının

bu nedenle genellikle , numaranız buna sığabiliyorsa ondalık tarafından sağlanan hassasiyet [10E38 ~ 38 basamak] olduğundan ve daha küçük Float depolama alanı (ve belki de hızı) önemli değildir ve anormal davranışlarla ve yaklaşık sayısal türlerle ilgili sorunlarla uğraşmaz. kabul edilebilir, genellikle Ondalık kullanın .

daha faydalı bilgiler

  • sayısal = ondalık (5 ila 17 bayt) ( Tam Sayısal Veri Türü)
    • .NET'te Ondalık ile eşlenecek
    • her ikisi de SQL sunucusunda varsayılan (kesinlik, ölçek) parametreleri (18, 0) içerir
    • ölçek = ondalık noktasının sağında saklanabilecek maksimum ondalık basamak sayısı.
    • paranın (8 bayt) ve smallmoney (4 bayt) da kesin olduğunu ve .NET'te Ondalık ile eşlendiğini ve 4 ondalık noktasına sahip olduğunu unutmayın ( MSDN )
    • ondalık ve sayısal (Transact-SQL) - MSDN
  • real (4 byte) ( Yaklaşık Sayısal Veri Türü)
  • kayan nokta (8 bayt) ( Yaklaşık Sayısal Veri Türü)
    • . NET'te Double ile eşleşecek
  • Hangi tür işlemci mimarisinin kullanıldığına veya sayıların büyüklüğüne bakılmaksızın tüm kesin sayısal türler her zaman aynı sonucu verir
  • Kayan nokta veri türüne sağlanan parametre , kayan nokta sayısının mantisini depolamak için kullanılan bit sayısını tanımlar .
  • Yaklaşık Sayısal Veri Türü genellikle daha az depolama alanı kullanır ve daha yüksek hıza (20x'e kadar) sahiptir ve ayrıca .NET'te ne zaman dönüştürüldüklerini de göz önünde bulundurmalısınız.

Tam Sayısal Veri Türleri Yaklaşık Sayısal Veri Türleri

ana kaynak : MCTS Kendi Hızınızda Eğitim Seti (Sınav 70-433): Microsoft® SQL Server® 2008 Veritabanı Geliştirme - Bölüm 3 - Tablolar, Veri Türleri ve Beyanlı Veri Bütünlüğü Ders 1 - Veri Türlerini Seçme (Yönergeler) - Sayfa 93


17
use the float or real data types only if the precision provided by decimal is insufficient- Ben gerçek daha sonra ondalık doğru daha az doğru olduğunu düşündüm, bu yüzden u ondalık yetersizse gerçek kullanmak için nasıl geliyor?
BornToCode

7
Gerçek doğruluk büyük sayılar ondalık (> 10e38) gereklidir veya boşluk hususlar alıntı araçlarının olası değerleri burada hassas tahmin .ı o büyük ve büyüklüğünü değil depolamak sürece tavsiye edilmez böylece daha az doğrudur
Iman

12
@BornToCode Buradaki "hassasiyet", depolamak istediğiniz değerlerin ne kadar geniş olduğunu ifade eder. 1e10 ve 1e-10 arasında değerleri depolamanız gerekiyorsa, o decimalzaman iyi olur. Bu 20'lik bir hassasiyettir. Örneğin, 1e20 ve 1e-20 arasındaki değerleri depolamanız gerekiyorsa, decimal bunu yapamazsınız . Bu 40 basamak hassasiyet. 1e20 ve 1e-20'yi aynı decimalalanda depolayamazsınız . Bunun yerine, floather şeyi dahili olarak taban 2'nin bir günlüğü olarak saklayabilirsiniz . Bu, yalnızca ilk ~ 8 basamağın doğru olacağı dezavantajı ile bir alanda tam bir hassasiyet aralığına izin verir.
Bacon Bits

Üçüncü BornToCode ve Iman'ın yorumları. Az önce denedim (SQL Server 2012 kullanarak) ve en yüksek hassasiyetli kayan nokta tipi olan şamandıra (53) için makine epsilon 2.22044604925031E-16 gibi görünüyor. Yani yaklaşık 15 önemli rakam elde edersiniz. Diğer yandan ondalık sayıdan 38 anlamlı rakam elde edebilirim.
Stewart

"Kullanın float..." - kim dedi? Bu bir teklif mi yoksa fikriniz mi?
user443854

24

MSDN'den yönergeler: Ondalık, kayan sayı ve gerçek Verileri kullanma

Sayısal ve ondalık veri türlerinin varsayılan maksimum hassasiyeti 38'dir. Transact-SQL'de sayısal, ondalık veri türüne işlevsel olarak eşdeğerdir. Veri değerlerinin tam olarak belirtildiği gibi saklanması gerektiğinde, ondalıklı sayıları saklamak için ondalık veri türünü kullanın.

Kayan ve gerçek davranışı, yaklaşık sayısal veri türleri hakkındaki IEEE 754 spesifikasyonunu izler. Şamandıra ve gerçek veri türlerinin yaklaşık yapısı nedeniyle, finansal uygulamalarda, yuvarlama içeren işlemlerde veya eşitlik denetimlerinde olduğu gibi tam sayısal davranış gerektiğinde bu veri türlerini kullanmayın. Bunun yerine, tamsayı, ondalık, para veya küçük para veri türlerini kullanın. WHERE yan tümcesi arama koşullarında, özellikle = ve <> işleçlerinde kayan nokta veya gerçek sütunlar kullanmaktan kaçının. Şamandıra ve gerçek sütunları> veya <karşılaştırmalarla sınırlamak en iyisidir.


(Sabit) ondalık sayı Scalesütunda belirtilir .
Cees Timmerman

1
'Tam olarak belirtildiği gibi' istiyorsanız, standart bakış açısından, numericasla istediğinizden daha hassas bir şekilde saklanmayacağından bazı avantajlar vardır : bkz. Stackoverflow.com/a/759606/626804
Ed Avis

13

Tam bir cevap değil, yararlı bir bağlantı:

"Sıklıkla ondalık değerlere karşı hesaplamalar yaparım. Bazı durumlarda, herhangi bir hesaplamadan önce ondalık değerlerin ASAP yüzdürülmesi için döküm daha iyi doğruluk sağlar."

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2008/12/20/for-better-precision-cast-decimals-before-calculations.aspx


2
Mantıklı değil. Kaynaklarla ilgili diğer tüm cevaplar, sayısal veya ondalık veri türlerinin doğru olduğunu ve kayan veya gerçek türlerin çok yakın bir yaklaşım olduğunu söylüyor. Daha düşük doğruluk nedeniyle, şamandıra dökmenin daha hızlı hesaplamalara izin verebileceğini, ancak daha yüksek hassasiyete sahip olmadığını anlayabiliyorum.
cbaldan

3
Tüm sayısal veri türlerinde taşma ve taşma görülebilir. Taşma açık bir hatadır, ancak taşma sessizdir. İçin aşağı taşma özellikleri decimalve floatvardır farklı . Ondalık, hassasiyeti veya ölçeği artırarak taşmaya karşı mümkün olduğunca korur. Ancak, ondalık sayıyla önemli basamakların sınırına ulaştığınızda, düşük akışlar sessizdir (ve hassasiyet kaybolur). Şamandıra daha geniş bir ölçek aralığına sahiptir ve aslında alt akışın nedeni olan ölçek sınırlamalarıdır. Böylece, şamandıra daha iyi bir ölçeğe sahip olabilir. Bununla birlikte, yine de olduğu hatalı türü.
ErikE

13

Veri Türü Önceliğinde Farklılıklar

Ondalık ve Sayısal işlevsel olarak aynıdır, ancak yine de bazı durumlarda önemli olabilecek veri türü önceliği vardır.

SELECT SQL_VARIANT_PROPERTY(CAST(1 AS NUMERIC) + CAST(1 AS DECIMAL),'basetype')

Sonuçta elde edilen veri türü sayısaldır çünkü veri türü önceliği alır .

Önceliğe göre veri türlerinin kapsamlı listesi:

Referans bağlantısı


7

Float değişken hassasiyete sahipken Decimal sabit bir hassasiyete sahiptir.

EDIT (tüm soru okunamadı): Float (53) (gerçek olarak da bilinir) SQL Server'da çift kesinlikli (32 bit) kayar nokta sayısıdır. Regular Float tek kesinlikli kayar nokta sayısıdır. Double, birçok hesaplama için hassasiyet ve basitliğin iyi bir kombinasyonudur. Ondalık sayıyla (136 bit'e kadar) çok yüksek bir hassasiyet numarası oluşturabilirsiniz, ancak hassasiyetinizi ve ölçeğinizi doğru bir şekilde tanımlamanıza da dikkat etmelisiniz, böylece tüm ara hesaplamalarınızı gerekli sayıda basamağa kadar içerebilir.


Dava finansal işlem için hangisinin tercih edileceğini belirtmediniz ve neden?
priyanka.sarkar

SQL Server 2008 ve üstü için float (53) aka float çift kesinlikli (64 bit) kayar nokta sayısı, float (24) aka real ise tek duyarlıklı (32 bit) kayar nokta sayısıdır. docs.microsoft.com/tr-tr/sql/t-sql/data-types/float-and-real-transact-sql
M Kloster

4

şamandıra nokta Yaklaşık sayı veri türüdür, yani veri türü aralığındaki tüm değerler tam olarak temsil edilemez.

Ondalık / Sayısal Sabit Hassasiyetli veri türüdür, yani veri türü aralığındaki tüm değerlerin tam olarak hassasiyet ve ölçekle temsil edilebileceği anlamına gelir. Para tasarrufu için ondalık kullanabilirsiniz.

Ondalık veya Sayısal'dan yüzdürmeye dönüştürmek bir miktar hassasiyet kaybına neden olabilir. Ondalık veya Sayısal veri türleri için SQL Server her bir kesinlik ve ölçek birleşimini farklı bir veri türü olarak görür. DECIMAL (2,2) ve DECIMAL (2,4) farklı veri türleridir. Bu, şamandıra için geçerli olmasa da 11.22 ve 11.2222'nin farklı türler olduğu anlamına gelir. FLOAT (6) için 11.22 ve 11.2222 aynı veri tipleridir.

Ayrıca kullanabilirsiniz Para tasarrufu için para veri türünü . Bu, para için 4 haneli hassasiyete sahip yerel veri türüdür. Çoğu uzman, para tasarrufu için bu veri türünü tercih eder.

Referans 1 2 3


3

Ondalık Dava

Temel ihtiyaç nedir?

Sonuçta, bilgisayarların dahili olarak sayıları ikili biçimde temsil etmesinden kaynaklanmaktadır. Bu, kaçınılmaz olarak yuvarlama hatalarına yol açar.

Bunu düşün:

0.1 (decimal, or "base 10") = .00011001100110011... (binary, or "base 2")

Yukarıdaki üç nokta [...] 'sonsuz' anlamına gelir. Dikkatlice bakarsanız, sonsuz tekrar eden bir desen vardır (= '0011')

Yani, bir noktada bilgisayarın bu değeri yuvarlaması gerekir. Bu, tam olarak saklanmayan sayıların tekrar tekrar kullanılmasından kaynaklanan birikim hatalarına yol açar.

Finansal tutarları (kesirli kısmı olabilecek rakamlar) saklamak istediğinizi varsayalım. Her şeyden önce, tamsayıları açıkça kullanamazsınız (tamsayıların kesirli bir kısmı yoktur). Tamamen matematiksel bir bakış açısından, doğal eğilim,float . Ancak, bir bilgisayarda, şamandıralar ondalık noktadan sonra bulunan sayının bir parçasına sahiptir - "mantis" - sınırlı. Bu yuvarlama hatalarına yol açar.

Bunu aşmak için, bilgisayarlar ondalık sayılar için bilgisayarlardaki ikili yuvarlama hatasını sınırlayan belirli veri türleri sunar. Bunlar, kesinlikle mali tutarları temsil etmek için kullanılması gereken veri türüdür. Bu veri türleri genellikle Decimal. Mesela C # 'da böyle. Veya DECIMALçoğu veritabanında.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.