2010-11-16 6 views
5

Ho riscontrato un problema con la precisione di SQL Server.Sql Server Precision Crazyness

ho le seguenti domande:

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 

che produce i seguenti risultati: rispettivamente

1079,762188

1079,762188

1079,7621875

1079,762187500000000000000000000

1079.7621875

La risposta corretta è: 1079.7621875.

Non capisco perché, quando i tipi hanno la stessa firma stanno perdendo precisione. Inoltre, perché passare da 30,14 a 30,15 risolve il problema di precisione? Inoltre, perché 20,15 hanno così tanti decimali in più rispetto a 30,15?

Ho letto questo articolo http://msdn.microsoft.com/en-us/library/ms190476(SQL.90).aspx e penso che dovrei andare bene perché le mie variabili hanno la stessa precisione.

Qualsiasi aiuto sarebbe molto apprezzato!

risposta

2

La risposta sta nel modo in cui i computer rappresentano i numeri internamente. A seconda della precisione che si utilizza, SQL Server allocherà 5, 9, 13 o 17 byte per rappresentare il proprio numero (vedere http://msdn.microsoft.com/en-us/library/ms187746(v=SQL.90).aspx) Quindi, ad esempio, quando si passa dalla precisione 30 alla precisione 20, la rappresentazione interna viene spostata da 17 byte a 13 byte. Come si imposta la scala su un numero di 17 byte rispetto a un numero di 13 byte dove una percentuale maggiore della rappresentazione del numero è dedicata alla scala (15/30 = 0,5, 15/20 = 0,75, cambia il comportamento di arrotondamento. .I tipi di numeri che abbiamo sono abbastanza buoni per la maggior parte delle applicazioni, ma a volte riceverai strani artefatti come quelli che vedi a causa del modo in cui abbiamo compromesso la rappresentazione dei numeri nei computer.

Per inciso, sii molto, molto attento ai tipi di galleggiante. Si approssimano approssimativamente ai numeri e ti daranno risultati molto sbagliati se usati in quantità. Sono eccellenti per la maggior parte delle applicazioni scientifiche quando in un calcolo non vengono utilizzati più di 20 numeri in virgola mobile. Se utilizzato in quantità, ad esempio aggiungendo 1 milione di numeri in virgola mobile in una somma (nome_colonna) si otterrà spazzatura. Dimostrazione di seguito:

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] 

Questo mi dà la seguente risposta su SQL Server 2008.

Numeric  Float 
0.0100000000 0.00999999999994859 
3

Questo è importante nella parte inferiore del collegamento che si è incollato:

  • La precisione e la scala risultato hanno un massimo assoluto di 38. Quando una precisione risultato è maggiore di 38, il corrispondente la scala è ridotta a impedendo il troncamento della parte integrale di un risultato .

Per tutti i risultati dove si ha una precisione di 30, la risultante precisione calcolata è 61. Poiché la massima precisione possibile è 38 la precisione risultante viene ridotto di 23. Pertanto, tutte le scale si stanno riducendo anche per evitare di troncare le parti integranti del risultato più del necessario.

Il 2 ° all'ultimo valore, in cui la precisione di ciascun valore è 20, la precisione risultante è 41, che deve essere ridotta solo di 3, lasciando una riduzione più leggera nella porzione di scala.

(30,15) funziona perché la scala risultante è 30, quindi, quando viene ridotto, è ancora abbastanza grande da contenere il valore desiderato.

Lezione: non fare precisione e ridimensionare a grandi dimensioni di quanto necessario, o otterrete risultati strani.

+0

Donnie, capisco che in (30,15) il risultato è 61 e viene ridotto a 38. Tuttavia basato sulla formula che ho visto sembra che la mia scala dovrebbe essere -2 o qualcosa del genere. Qual è la formula per determinare qual è la scala? – zgirod