2012-06-20 21 views
6

Devo convertire un float in decimale (28,10) in SQL Server. Il mio problema è che, a causa della natura del float e del modo in cui vengono eseguite le conversioni, il semplice lancio del float potrebbe far apparire il numero sbagliato ai miei utenti.Converti virgola mobile in virgola mobile (SQL Server)

Ad esempio:

Float:    280712929.22 
Cast as Decimal:  280712929.2200000300 
What I think I want: 280712929.2200000000 

ho capito un po 'sulle opere float modo (che si tratta di un tipo di dati approssimativi, ecc), ma certamente non abbastanza per capire il motivo per cui si aggiunge il 300 alla fine. È semplicemente immondizia come un effetto collaterale della conversione, o è in qualche modo una rappresentazione più accurata di ciò che il float effettivamente memorizza? A me sembra che abbia tirato fuori la precisione dal nulla.

In definitiva, ho bisogno che sia accurato, ma anche di guardare "giusto". Penso di aver bisogno di ottenere quel numero minimo, poiché sembra che abbia appena aggiunto zero finali. È possibile? Questa è una buona o cattiva idea, e perché? Altri suggerimenti sono benvenuti.

Alcuni altri esempi:

Float:   364322379.5731 
Cast as Decimal: 364322379.5730999700 
What I want:  364322379.5731000000 

Float:   10482308902 
Cast as Decimal: 10482308901.9999640000 
What I want:  10482308902.0000000000 

Nota a margine: la nuova tabella di database che sto mettendo questi valori in è leggibile da mio utente. In questo momento hanno solo bisogno di due cifre decimali, ma potrebbe cambiare in futuro, quindi abbiamo deciso di utilizzare Decimal (28,10). L'obiettivo a lungo termine è quello di convertire le colonne float da cui ottengo i miei dati anche in decimali.

MODIFICA: A volte i float che ho hanno più cifre decimali di quanto io abbia mai bisogno, ad esempio: -0.628475064730907. In questa situazione il cast a -0.6284750647 va bene. Fondamentalmente ho bisogno del mio risultato per aggiungere zero alla fine del float fino a che non ho 10 cifre decimali.

+0

Forse ho trovato la risposta. http://stackoverflow.com/questions/34316871/how-can-the-following-result-of-casting-from-float-to-numeric-be-explained –

risposta

8

È necessario lanciare una volta per turno, e una volta per aggiungere cifre decimali di nuovo (ci sono altri modi, sicuramente, utilizzando STR, ROUND ecc):

DECLARE @c TABLE(x FLOAT); 

INSERT @c SELECT 280712929.22; 
INSERT @c SELECT 364322379.5731; 
INSERT @c SELECT 10482308902; 

SELECT x, 
    d = CONVERT(DECIMAL(28,10), x), 
    rd = CONVERT(DECIMAL(28,10), CONVERT(DECIMAL(28,4), x)) 
FROM @c; 

Risultati:

x    d      rd 
-------------- ---------------------- ---------------------- 
280712929.22 280712929.2200000300 280712929.2200000000 
364322379.5731 364322379.5730999700 364322379.5731000000 
10482308902  10482308902.0000000000 10482308902.0000000000 

Se vuoi che sia accurato e guardi bene, smetti di usare FLOAT, che è un tipo di dati approssimativo e sfida la logica per la maggior parte delle persone al di fuori di uno sfondo matematico rigoroso. Utilizzare DECIMAL con una scala più grande del necessario e formattarlo al numero di posizioni decimali necessarie ora (nelle query o creare una vista o creare una colonna calcolata). Se memorizzi più informazioni di quelle che ti servono ora, puoi sempre esporle più tardi. Puoi anche scegliere di non concedere agli utenti l'accesso diretto alla tua tabella.

+0

il numero di numeri decimali può differire, almeno questo è cosa penso. –

+0

Questo aiuta in una certa misura.Tuttavia, ciò significa che troncerò le cifre al di fuori dei float, dove in realtà ho più di 4 cifre decimali, ad esempio: 517822.18109027. Modifica il post per chiarire. –

+2

Se è necessario decidere in modo condizionale quante posizioni decimali visualizzare su ogni riga, in base al valore in quella riga, penso che si stia attraversando il territorio di analisi/formattazione delle stringhe. Probabilmente è meglio farlo a livello di presentazione, non nel database. –

1

Non sono sicuro se questo cade sotto necropostazione, ma ho avuto un problema simile recentemente, quindi ho pensato di poter postare.

Questo potrebbe essere brutto come il peccato, ma sembrava funzionare (modificato dalla risposta di Aaron sopra).

DECLARE @myTable TABLE(x FLOAT); 

INSERT INTO @myTable VALUES 
    (280712929.22), 
    (364322379.5731), 
    (10482308902), 
    (-0.628475064730907); 

SELECT x, 
     d = CONVERT(DECIMAL(28,10), x),     
     NewDec = CONVERT(DECIMAL(28,10),   
         CONVERT(DECIMAL(16,15), 
           LEFT(CONVERT(VARCHAR(50), x, 2),17)) 
         * POWER(CONVERT(DECIMAL(38,19),10), 
           RIGHT(CONVERT(varchar(50), x,2),4)))      
FROM @myTable; 

Risultati:

x     d      NewDec 
------------------ ---------------------- ---------------------- 
280712929.22  280712929.2200000300 280712929.2200000000 
364322379.5731  364322379.5731000300 364322379.5731000000 
10482308902   10482308902.0000000000 10482308902.0000000000 
-0.628475064730907 -0.6284750647   -0.6284750647