2010-11-16 10 views
5

Tengo un problema con la precisión del servidor sql.Sql Server Precision Crazyness

tengo las siguientes consultas:

DECLARE @A numeric(30,10) 
DECLARE @B numeric(30,10) 
SET @A = 20.225 
SET @B = 53.3875 
SELECT @A * @B 

DECLARE @A1 numeric(30,14) 
DECLARE @B1 numeric(30,14) 
SET @A1 = 20.225 
SET @B1 = 53.3875 
SELECT @A1 * @B1 

DECLARE @A3 numeric(30,15) 
DECLARE @B3 numeric(30,15) 
SET @A3 = 20.225 
SET @B3 = 53.3875 
SELECT @A3 * @B3 

DECLARE @A2 numeric(20,15) 
DECLARE @B2 numeric(20,15) 
SET @A2 = 20.225 
SET @B2 = 53.3875 
SELECT @A2 * @B2 

DECLARE @A4 float 
DECLARE @B4 float 
SET @A4 = 20.225 
SET @B4 = 53.3875 
SELECT @A4 * @B4 

que da los siguientes resultados: respectivamente

1079.762188

1079.762188

1079.7621875

1,079.762187500000000000000000000

1079.7621875

La respuesta correcta es: 1079.7621875.

No entiendo por qué, cuando los tipos tienen la misma firma, están perdiendo precisión. Además, ¿por qué pasar de 30,14 a 30,15 soluciona el problema de precisión? Además, ¿por qué 20,15 tiene tantos decimales más que 30,15?

He leído este artículo http://msdn.microsoft.com/en-us/library/ms190476(SQL.90).aspx y creo que debería estar bien porque mis variables tienen la misma precisión.

¡Cualquier ayuda sería muy apreciada!

Respuesta

2

La respuesta está en cómo las computadoras representan los números internamente. Dependiendo de la precisión que use, SQL Server asignará 5, 9, 13 o 17 bytes para representar su número (consulte http://msdn.microsoft.com/en-us/library/ms187746(v=SQL.90).aspx). Por ejemplo, cuando pasó de la precisión 30 a la precisión 20, la representación interna pasó de 17 bytes a 13 bytes. Cómo establece la escala en un número de 17 bytes frente a un número de 13 bytes donde una mayor proporción de la representación numérica está dedicada a la escala (15/30 = 0.5, 15/20 = 0.75, cambia el comportamiento de redondeo. No hay una respuesta perfecta .Los tipos de números que tenemos son lo suficientemente buenos para la mayoría de las aplicaciones, pero a veces obtendrás artefactos extraños como los que estás viendo debido a la forma en que nos hemos comprometido a representar números en las computadoras.

Como un lado, tenga mucho, mucho cuidado con los tipos de flotador. Solo aproximan aproximadamente los números y te darán resultados muy incorrectos cuando se usen en cantidad. Son excelentes para la mayoría de las aplicaciones científicas cuando no se utilizan más de 20 números de punto flotante en un solo cálculo. Cuando se usa en cantidad, digamos agregando 1 millón de números de punto flotante en una suma (column_name) obtendrá basura. por debajo de la demostración:

DECLARE @f FLOAT 
DECLARE @n NUMERIC(20,10) 
DECLARE @i INT 

SET @f = 0 
SET @n = 0 
SET @i = 0 

WHILE @i < 1000000 
BEGIN 
    SET @f = @f + 0.00000001 
    SET @n = @n + 0.00000001 
    SET @i = @i + 1 
END 

SELECT @n as [Numeric], @f as [Float] 

Esto me da la siguiente respuesta en SQL Server 2008.

Numeric  Float 
0.0100000000 0.00999999999994859 
3

Esto es importante en la parte inferior del enlace que ha pegado:

  • La precisión y la escala consecuencia tienen un máximo absoluto de 38. Cuando una precisión resultado es mayor que 38, el correspondiente la escala se reduce a para evitar que se trunque la parte integral de un resultado .

Para todos los resultados donde se tiene una precisión de 30, la precisión calculada resultante es 61. Dado que la máxima precisión posible es 38 la precisión resultante se reduce en 23. Así, todas las escalas se están reduciendo también para evitar truncar las partes integrales del resultado más de lo absolutamente necesario.

El 2do al último valor, donde la precisión de cada valor es 20, la precisión resultante es 41, que solo necesita reducirse en 3, dejando una reducción más ligera en la porción de escala.

(30,15) funciona porque la escala resultante es 30, por lo tanto, cuando se reduce, sigue siendo lo suficientemente grande como para mantener el valor que desea.

Lección: No hagas que la precisión y la escala sean mayores de lo que necesitas, o obtendrás resultados extraños.

+0

Donnie, entiendo que en el (30,15) el resultado es 61 y se reduce a 38. Sin embargo basado en la fórmula que vi, parece que mi escala debería ser -2 o algo así. ¿Cuál es la fórmula para determinar qué es la escala? – zgirod