2009-08-29 15 views
15

Ho una lettura di input che cambia dinamicamente da un file. I numeri sono Int o Double. Perché Scala stampa .0 dopo ogni numero ? C'è un modo per Scala di stamparlo nello stesso modo in cui lo legge?Formattazione numero in Scala?

Esempio:

var x:Double = 1 
println (x)    // This prints '1.0', I want it to print '1' 
x = 1.0     // This prints '1.0', which is good 

Non posso usare Int perché alcuni degli input ricevo sono Double s. Non riesco a utilizzare String o AnyVal perché eseguo alcune operazioni matematiche.

Grazie,

risposta

7

Uso printf:

printf("The value is %.0f", x) 

Per una descrizione della stringa di formato, vedere this page dalla documentazione delle API Java SE 6.

Si noti che è anche possibile utilizzare la libreria Java di Scala, quindi è possibile utilizzare anche altri modi per formattare numeri da Java. Si può ad esempio l'uso di classe java.text.DecimalFormat:

val df = new java.text.DecimalFormat("#####") 
println(df.format(x)) 
+0

Grazie per si risponde Ma il problema è che il numero è sconosciuto, o è '1' o '1.0'. Se '1' voglio stampare '1', se è '1.0', allora voglio stampare '1.0'. Ma poiché è doppio, Scala stampa sempre come "1.0" –

+3

Se lo desideri, dovrai archiviarlo come stringa. Un 'double' non ricorda se lo hai assegnato o meno con' 1' o '1.0'. – cdmckay

+2

Kodo, i numeri non hanno intrinsecamente un numero di cifre. Non c'è differenza tra un numero che ha il valore 1 e un numero che ha il valore 1.0. – Jesper

9
var x:Double = 1 
var y:Double = 1.0 

print(x) // => 1.0 
print(y) // => 1.0 

Se ho capito si mette in discussione che si desidera scala stampare X e Y in modo diverso? Il problema è che xey sono entrambe variabili del tipo Double e hanno lo stesso aspetto.

Perché si definisce esplicitamente il tipo di vars?

var x = 1 
var y= 1.0 

print(x) // => 1 
print(y) // => 1.0 
+0

Ha detto "modifica dinamica della lettura degli input da un file". Porta i numeri e i numeri possono essere interi o meno (ma sempre memorizzati come Double). – akauppi

1

Utilizzare l'inferenza del tipo piuttosto che la digitazione esplicita.

scala> val xi = 1 
xi: Int = 1 

scala> val xd = 1.0 
xd: Double = 1.0 

scala> println(xi) 
1 

scala> println(xd) 
1.0 
+0

Ooops spiacente questa è una risposta duplicata. – Synesso

29
scala> "%1.0f" format 1.0 
res3: String = 1 

Se il vostro ingresso è sia Int o Double, si può fare in questo modo:

def fmt(v: Any): String = v match { 
    case d : Double => "%1.0f" format d 
    case i : Int => i.toString 
    case _ => throw new IllegalArgumentException 
} 

Usage:

scala> fmt(1.0) 
res6: String = 1 

scala> fmt(1) 
res7: String = 1 

scala> fmt(1.0f) 
java.lang.IllegalArgumentException 
     at .fmt(<console>:7) 
     at .<init>(<console>:6) 
     at .<clinit>(<console>) 
     at RequestResult$.<init>(<console>:4) 
     at RequestResult$.<clinit>(<console>) 
     at RequestResult$result(<console>) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.Dele... 

In caso contrario, si potrebbe utilizzare BigDecimals. Sono lenti, ma lo fanno venire con la scala, così "1", "1,0" e "1,00" sono tutti diversi:

scala> var x = BigDecimal("1.0") 
x: BigDecimal = 1.0 

scala> x = 1 
x: BigDecimal = 1 

scala> x = 1.0 
x: BigDecimal = 1.0 

scala> x = 1.000 
x: BigDecimal = 1.0 

scala> x = "1.000" 
x: BigDecimal = 1.000 
+0

È orribile. Hai appena lanciato tutta la sicurezza del tipo fuori dalla finestra. Il modo più semplice è quello di fare: n.toInt.toString – juancn

+4

@juancn Come ho fatto a buttare la sicurezza tipo fuori dalla finestra? A proposito, "' var n = 1.0; n.toInt.toString' "produce' 1', non '1.0' come desiderato. –

+2

Il fatto è che in 'fmt' stai dichiarando di accettare 'Qualsiasi' che in realtà non è vero, perché lanci una IllegalArgumentException se passo, ad esempio, una stringa. Si potrebbe fare qualcosa del tipo: 'def fmt [T <% math.ScalaNumericConversions] (n: T) = if (n.toInt == n) n.toInt.toString else n.toString' che è sicuro. eccezioni argomento illegali devono essere gettati solo se il sistema di tipo non può esprimere un insieme ragionevole di vincoli (ad esempio, scala non consente di specificare numeri interi a distanza come tipi). – juancn

4

L'uso di un "_.0" alla fine della virgola mobile i numeri sono una convenzione. Solo un modo per sapere che il numero è effettivamente a virgola mobile e non un intero.

Se si davvero è necessario "stamparlo nello stesso modo in cui lo legge", potrebbe essere necessario rivedere il modo in cui il codice è strutturato, possibilmente preservando i dati di input.Se è solo un problema di formattazione, il modo più semplice è quello di convertire i valori a numeri interi prima della stampa:

val x = 1.0 
println(x.toInt) 

Se alcuni sono interi e alcuni non lo sono, è necessario un codice po 'di più:

def fmt[T <% math.ScalaNumericConversions](n : T) = 
        if(n.toInt == n) n.toInt.toString else n.toString 

val a : Double = 1.0 
val b : Double = 1.5 
val c : Int = 1 

println(fmt(a)) 
println(fmt(b)) 
println(fmt(c)) 

il codice di cui sopra dovrebbe stampare:

1 
1.5 
1 

la firma del metodo fmt accetta qualsiasi tipo che o è un sottotipo di ScalaNumericConversions o può essere convertito in un attraverso conversioni implicite (quindi possiamo usare il metodo toInt).

2

Partendo Scala 2.10 è possibile utilizzare the f interpolator:

scala> val x: Double = 1 
x: Double = 1.0 

scala> println(f"$x%.0f") 
1 

scala> val i = 1 
i: Int = 1 

scala> println(f"$i%.0f") 
1