2013-08-22 5 views
25
package main 

import (
    "fmt" 
    "strconv" 
    ) 

func main() { 
    k := 10/3.0 
    i := fmt.Sprintf("%.2f", k) 
    f,_ := strconv.ParseFloat(i, 2) 
    fmt.Println(f) 
} 

ho dovuto scrivere il programma di cui sopra per diminuire la precisione di una variabile go float64 a 2. In questo caso stavo usando sia StrConv e FMT. C'è qualche altro metodo logico con cui può essere fatto?Come possiamo troncare il tipo float64 a una particolare precisione in golang?

+7

Perché si vuole diminuire la precisione di una variabile float64? –

+2

Durante la visualizzazione dei dati in html, non volevo visualizzare o memorizzare più di 2 cifre. Stavo affrontando la situazione in cui dovevo convertirlo in stringa, quindi pensavo a metodi alternativi. –

+7

Usare semplicemente fmt.Sprintf ("%. 2f", k) quando lo si mostra in html è probabilmente il modo migliore per farlo. –

risposta

46

non hai bisogno di alcun codice aggiuntivo ... la sua semplice come

import (
    "fmt" 
) 

func main() { 
    k := 10/3.0 
    fmt.Printf("%.2f", k) 
} 

Test Code

+0

Questa è di gran lunga la risposta più utile. Non sono sicuro del motivo per cui non è accettato. – dsifford

+2

Non se si esegue un benchmark;) – creack

+1

Questo non è arrotondato, è troncamento. Inoltre, funziona fintanto che il risultato dell'operazione è destinato a essere stampato, ma operazioni aggiuntive richiederebbero di analizzare il numero in un float. Golang dovrebbe davvero supportare l'arrotondamento nella libreria. La soluzione migliore che ho trovato è quella di utilizzare il pacchetto decimale. github.com/shopspring/decimal –

9

io davvero non vedo il punto, ma si poteva fare qualcosa di simile senza StrConv:

package main 

import (
    "fmt" 
) 

func main() { 
    untruncated := 10/3.0 
    truncated := float64(int(untruncated * 100))/100 
    fmt.Println(untruncated, truncated) 
} 
+1

+1. Risolto un piccolo refuso. Anche qui c'è un gioco Go: http://play.golang.org/p/RFy6cN148X – Matt

+1

Questa non è la stessa cosa, considera che la conversione in int non verrà completata.http: //play.golang.org/p/ ehMAFopHTX – Isaiah

+1

In effetti, non arrotonda, tronca. Se vuoi arrotondare, puoi giocare con il pacchetto matematico. – creack

-2

modificare dalla @creack

package main 

import (
    "fmt" 
) 

func main() { 

    //untruncated := 10/3.0 
    untruncated := 4.565 
    tmp := int(untruncated*100) 
    last := int(untruncated*1000)-tmp*10 
    if last>=5{ 
     tmp += 1 
    } 
    truncated := float64(tmp)/100 

    fmt.Println(untruncated, truncated) 
} 
51

Sto appena iniziando in Go e ho trovato sorprendente il fatto che non ha né una funzione "toxxed" (come in JavaScript), che realizzerebbe ciò che si desidera, né una funzione "rotonda".

presi una funzione round one-liner da altrove, e anche fatto toFixed() che dipende rotondo():

func round(num float64) int { 
    return int(num + math.Copysign(0.5, num)) 
} 

func toFixed(num float64, precision int) float64 { 
    output := math.Pow(10, float64(precision)) 
    return float64(round(num * output))/output 
} 

utilizzati:

fmt.Println(toFixed(1.2345678, 0)) // 1 
fmt.Println(toFixed(1.2345678, 1)) // 1.2 
fmt.Println(toFixed(1.2345678, 2)) // 1.23 
fmt.Println(toFixed(1.2345678, 3)) // 1.235 (rounded up) 
+1

Perché è stato downvoted? Voglio sapere come migliorarlo. Grazie. –

+1

Mi sembra buono! Sto usando il tuo lavoro così com'è. –

+7

Probabilmente down-votato perché in alcuni casi fa delle risposte un po 'errate, e in altri ha delle risposte sbagliate; specialmente dove viene richiesta alta "precisione". cioè 'toFixed (92234, 14)' -> "-92233.72036854776" – rvalue

5

nessuno ha menzionato usando math/big. I risultati relativi alla domanda originale sono gli stessi della risposta accettata, ma se stai lavorando con float che richiedono un certo grado di precisione ($ money $), allora dovresti usare big.Float.

Per la domanda iniziale:

package main 

import (
    "math/big" 
    "fmt" 
) 

func main() { 
    // original question 
    k := 10/3.0 
    fmt.Println(big.NewFloat(k).Text('f', 2)) 
} 

Purtroppo, si può vedere che .Text non usa la modalità di arrotondamento definito (in caso contrario questa risposta potrebbe essere più utile), ma piuttosto sembra sempre di arrotondare verso lo zero:

j := 0.045 
fmt.Println(big.NewFloat(j).SetMode(big.AwayFromZero).Text('f', 2) 

// out -> 0.04 

Tuttavia, ci sono alcuni vantaggi ad aver memorizzato il float come big.Float.

+1

Come utilizzare altre modalità di arrotondamento è descritto [in questo numero su GitHub] (https://github.com/golang/go/issues/18649#issuecomment- 274994822): "Se hai bisogno di arrotondare piuttosto che farlo prima di formattare e ottieni il risultato desiderato: https://play.golang.org/p/iSo7VROcPj" – Tobi

0

Questo è un po soluzione come si può galleggiare rotondo con la conversione del tipo a int avanti e indietro:

package main 

import (
    "fmt" 
) 

func main() { 
    k := 10/3.0 
    k = float64(int(k*100))/100 
    fmt.Println(k) // output 3.33 
} 

https://play.golang.org/p/yg2QYcZ-2u

0

Il answer da threeve mi ha portato a this issue su GitHub in cui una soluzione basata su math/big per i valori di arrotondamento viene presentato - in questo modo il metodo di arrotondamento viene utilizzato correttamente:

package main 

import (
    "fmt" 
    "math/big" 
) 

func main() { 
    f := new(big.Float).SetMode(big.ToNearestEven).SetFloat64(10/3.0) 
    // Round to 2 digits using formatting. 
    f.SetPrec(8) 
    fmt.Printf("%.2f\n", f) 
} 

La modalità di arrotondamento è anche rispettato l'esempio di threeve:

j := 0.045 

f := new(big.Float).SetMode(big.AwayFromZero).SetFloat64(j) 
// Round to 2 digits using formatting. 
f.SetPrec(8) 
fmt.Printf("%.2f\n", f) 

-> produce correttamente 0.05

Inoltre, Go 1.10 è stato rilasciato e ha aggiunto una funzione math.Round(), questa risposta eccellente da icza: Golang Round to Nearest 0.05

package main 

import (
    "fmt" 
    "math" 
) 

func main() { 

    fmt.Println(Round(10/3.0, 0.01)) 

} 

func Round(x, unit float64) float64 { 
    return math.Round(x/unit) * unit 
} 

Tuttavia, non è necessario utilizzare float per la memorizzazione di valori monetari. (Vedere: Why not use Double or Float to represent currency?) Un modo per aggirare questo sta usando una libreria che implementa decimal come https://github.com/ericlagergren/decimal o https://github.com/shopspring/decimal