2009-01-08 14 views
16

¿Alguien sabe por qué, utilizando SQL Server 2005división decimal de T-SQL Precisión

SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,9),12499999.9999) 

me da 11,74438969709659,

pero cuando puedo aumentar el número de decimales en el denominador a 15, aparece un menos preciso respuesta:

SELECT CONVERT(DECIMAL(30,15),146804871.212533)/CONVERT(DECIMAL (38,15),12499999.9999) 

dame 11,74438969

+0

BTW la calculadora de Windows da 11.744389697096595117576772760941 – inspite

Respuesta

23

Para la multiplicación simplemente sumar el número de decimales en cada argumento juntos (usando lápiz y papel) para elaborar salida lugares dec.

Pero la división solo hace volar la cabeza. Me voy a acostar ahora.

En términos de SQL sin embargo, es exactly as expected.

--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) 

Usted puede hacer lo mismo matemáticas si seguir this rule también, si usted trata a cada par de números como

  • 146804871,212533000000000 y 12499999,999900000
  • 146804871,212533000000000 y 12499999.999900000000000
+0

Gracias. Para ser sincero, usé un FLOTADOR para mi problema particular (ya que no necesito ser 100% exacto), pero estaba confundido como lo que estaba pasando cuando estaba usando decimales. –

+1

SQL server es lamentablemente muy malo en aritmética :(Por lo tanto, también vale la pena mencionar que, si necesita resultados precisos para la multiplicación y división en t-sql, la mejor opción es: Definir y usar funciones CLR. Consulte: http : //www.skylinetechnologies.com/Insights/Skyline-Blog/March-2013/CLR-Functions-in-SQL-Server-A-Tutorial para una buena introducción –

2

Convertir la expresión no los argumentos.

select CONVERT(DECIMAL(38,36),146804871.212533/12499999.9999) 
14

Para decirlo brevemente, use DECIMAL (25,13) y estará bien con todos los cálculos: obtendrá la precisión correcta declarada: 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á seguro! ¿Por qué es esto? ¡Debido a la mala implementación de la aritmética en SQL Server! Hasta que lo arreglen, siga esa regla.

+0

¿Hay algún material de referencia para decir por qué esto será "correcto" "para todos los cálculos? – MrEdmundo

+0

' select cast (1000000 como DECIMAL (38,19))/cast (9223372036854775807 como DECIMAL (38,19)); '<< OK ' select cast (1000000 como DECIMAL (25,13))/cast (9223372036854775807 como DECIMAL (25,13)); '<< Desbordamiento aritmético – Triynko

8

me he dado cuenta de que si lanzas el valor de división para flotar, le da la respuesta correcta, es decir:

select 49/30     (result = 1) 

se convertiría en:

select 49/cast(30 as float) (result = 1.63333333333333) 
4

Estábamos dándole vueltas a la magia transición,

P & S están vinculados, por lo que:

  1. (72,54) -> (38,29)

  2. (84,54) -> (38,8)

Suponiendo (38,29) es un error y debe ser (38,20), la siguiente es la matemática:

  1. i.72 - 38 = 34, ii. 54 - 34 = 20

  2. i. 84 - 58 = 46, ii. 54 - 46 = 8

Y este es el razonamiento:

i. La precisión de salida menos la precisión máxima son los dígitos que vamos a descartar.

ii. Entonces, 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 tratando de dar sentido a esto.

0

Puede ayudar:

SELECT COL1 * 1.0/COL2 
+0

¿Por qué crees eso? –

Cuestiones relacionadas