SQL Server Ondalık İşlem Doğru Değil

Oct 27 2020

Bu basit işlemi SQL sunucusunda çalıştırdığımda:

Select 800.0 /30.0 

26.666666 değerini alıyorum, burada 6 basamak için yuvarlasa bile 26.666667 olmalıdır. Hesaplamanın doğru olmasını nasıl sağlayabilirim? Çevrimiçi olarak araştırmaya çalıştım ve işlemden önce her işleneni yüksek hassasiyetli bir ondalık sayıya çevirdiğim bir çözüm buldum, ancak bu benim için uygun olmayacak çünkü çok uzun karmaşık hesaplamalarım var. daha iyi bir çözüm olması gerektiğini düşünüyorum.

Yanıtlar

2 Larnu Oct 26 2020 at 23:46

Kullanan bir bölme olduğunda, SQL Server'da, elde edilen ölçekten sonraki tüm rakamlar yuvarlatılmaz, kesilir. İfadeniz için a decimal(4,1)ve a var decimal(3,1), bu da a decimal(10,6):

Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Scale = max(6, s1 + p2 + 1)

Sonuç olarak, 26.66666666666666~şeklinde kısaltıldı 26.666666.

Hassasiyet ve ölçeğin boyutunu artırarak ve ardından CONVERTgerekli hassasiyet ve ölçeğinize geri dönerek bunu aşabilirsiniz. Örneğin, duyarlık ve ölçeği artırmak decimal(3,1)için decimal(5,2)ve geri dönüştürmek decimal(10,6):

SELECT CONVERT(decimal(10,6),800.0 / CONVERT(decimal(5,3),30.0));

Bu geri döner 26.666667.

CR241 Oct 26 2020 at 23:50

Bu yardımcı olabilir:

ROUND (Transact-SQL) kullanın

SELECT ROUND(800.0 /30.0, 5) AS RoundValue;

Sonuç:

RoundValue

26.666670
seanb Oct 27 2020 at 08:41

Sanırım bunun nedeni SQL Server'ın sayılarınızı decimaldeğerler olarak almasıdır (örneğin, 6.6666 ve 6.6667 tam olarak bu değerler, 6 ve üçte ikisi değil) değil float(yaklaşık sayılarla çalışabilir).

floatBaşlangıçta bunu açık bir şekilde a çevirirseniz / dönüştürürseniz , hesaplamalarınızın sorunsuz çalışmasını sağlamalısınız.

İşte arasındaki farkı göstermek için bazı örnekler var int, decimalve floathesaplamalar

  • 20'yi 3'e bölme
  • 20'yi 3'e bölerek, sonra tekrar 3 ile çarparak (matematiksel olarak 20 olmalıdır).
SELECT  (20/3)                             AS int_calc,
        (20/3) * 3                         AS int_calc_x3,
        (CAST(20 AS decimal(10,3)) /3)     AS dec_calc,
        (CAST(20 AS decimal(10,3)) /3) * 3 AS dec_calc_x3,
        (CAST(20 AS float) /3)             AS float_calc,
        (CAST(20 AS float) /3) * 3         AS float_calc_x3

aşağıdaki sonuçlarla

int_calc   int_calc_x3   dec_calc   dec_calc_x3   float_calc         float_calc_x3
6         18             6.666666   19.999998     6.66666666666667   20

Senin durumunda kullanabilirsin

Select CAST(800.0 AS float) /30.0

26.6666666666667 ile sonuçlanır

Daha sonra 30 ile çarparsanız, doğru sonucu alır, örneğin,

Select (CAST(800.0 AS float) /30.0) * 30

800 ile sonuçlanır. Ondalık sayılarla ilgilenen çözümler buna sahip olmayacaktır.

Ayrıca, onu bir kayan nokta olarak elde ettiğinizde, bir ondalık sayıya veya bir şekilde int'e dönüştürülene kadar (örneğin, bir tabloya int olarak kaydedilene kadar) bir kayan nokta olarak kalması gerektiğini unutmayın. Yani...

SELECT A.Num / 30
FROM (Select ((CAST(800.0 AS float) /30.0) * 30) AS Num) AS A

yine de 26.6666666666667 ile sonuçlanacaktır

Umarım bu uzun karmaşık hesaplamalarınızda size yardımcı olacaktır.