Precisión de la división decimal de T-SQL
Pregunta
¿Alguien sabe por qué, utilizando SQLServer 2005
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
me da 11.74438969709659,
pero cuando incremento los decimales en el denominador a 15, obtengo una respuesta menos precisa:
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
dame 11.74438969
Solución
Para la multiplicación, simplemente sumamos la cantidad de lugares decimales en cada argumento juntos (con lápiz y papel) para calcular los lugares de salida.
Pero la división te hace volar la cabeza. Me voy a recostar ahora.
Sin embargo, en términos SQL, es exactamente como se espera.
--Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
--Scale = max(6, s1 + p2 + 1)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 9 + 54 = 72
--Max P = 38, P & S are linked, so (72,54) -> (38,20)
--So, we have 38,20 output (but we don use 20 d.p. for this sum) = 11.74438969709659
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999)
--Scale = 15 + 38 + 1 = 54
--Precision = 30 - 15 + 15 + 54 = 84
--Max P = 38, P & S are linked, so (84,54) -> (38,8)
--So, we have 38,8 output = 11.74438969
SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999)
Puede hacer los mismos cálculos matemáticos si sigue esta regla también, si tratas cada par de números como
- 146804871.212533000000000 y 12499999.999900000
- 146804871.212533000000000 y 12499999.999900000000000
Otros consejos
Para decirlo brevemente, use DECIMAL (25,13) y estará bien con todos los cálculos: obtendrá la precisión correcta tal como se declara: 12 dígitos antes del punto decimal y 13 dígitos decimales después. La regla es: p + s debe ser igual a 38 y estarás en el lado seguro! ¿Por qué es esto? Debido a la muy mala implementación de la aritmética en SQL Server! Hasta que lo arreglen, sigue esa regla.
Me he dado cuenta de que si pones el valor de división a flotar, te da la respuesta correcta, es decir:
select 49/30 (result = 1)
se convertiría en:
select 49/cast(30 as float) (result = 1.63333333333333)
Estábamos desconcertados sobre la transición mágica,
P & amp; S están vinculados, por lo que:
(72,54) - > (38,29)
(84,54) - > (38,8)
Suponiendo que (38,29)
es un error tipográfico y debería ser (38,20)
, la siguiente es la matemática:
-
i. 72 - 38 = 34, ii. 54 - 34 = 20
-
i. 84 - 58 = 46, ii. 54 - 46 = 8
Y este es el razonamiento:
i. Precisión de salida menos precisión máxima son los dígitos que vamos a tirar.
ii. Luego, la escala de salida, menos lo que vamos a tirar, nos da ... los dígitos restantes en la escala de salida.
Espero que esto ayude a cualquier otra persona que intente darle sentido a esto.
Convierte la expresión no los argumentos.
select CONVERT(DECIMAL(38,36),146804871.212533 / 12499999.9999)
El uso de lo siguiente puede ayudar:
SELECT COL1 * 1.0 / COL2