2009-08-29 17 views
15

Tengo una lectura de entrada que cambia dinámicamente desde un archivo. Los números son Int o Double. ¿Por qué Scala imprime .0 después de cada número Double? ¿Hay alguna manera de que Scala lo imprima de la misma manera que lo lee?Formato numérico en Scala?

Ejemplo:

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 

No puedo utilizar Int porque parte de la entrada de recibo son Double s. No puedo usar String o AnyVal porque realizo algunas operaciones matemáticas.

Gracias,

Respuesta

7

Uso printf:

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

Para una descripción de la cadena de formato, consulte this page de la documentación de la API de Java SE 6.

Tenga en cuenta que también puede utilizar la biblioteca Java de Scala, por lo que también se pueden usar otras formas de formatear números desde Java desde Scala. Se puede, por ejemplo, clase de uso java.text.DecimalFormat:

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

Gracias por la contestación pero el problema es que el número se desconoce, o bien es '1' o '1.0'. Si '1' quiero imprimir '1', si es '1.0' entonces quiero imprimir '1.0'. Pero como es doble, Scala siempre imprime como '1.0' –

+3

. Si lo desea, deberá almacenarlo como una cadena. Un 'doble' no recuerda si le asignó' 1' o '1.0'. – cdmckay

+2

Kodo, los números no tienen inherentemente una cantidad de dígitos. No hay diferencia entre un número que tiene el valor 1 y un número que tiene el valor 1.0. – Jesper

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

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

si entiendo que pregunta que desea imprimir Scala X e Y de manera diferente? El problema es que xey son una variable del tipo Doble y tienen el mismo aspecto.

¿Por qué define explícitamente el tipo de vars?

var x = 1 
var y= 1.0 

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

Dijo "cambio dinámico de la lectura de entrada de un archivo". Está ingresando números, y los números pueden ser enteros o no (pero siempre almacenados como un Doble). – akauppi

1

Utilice la inferencia tipo, en lugar de escribir explícitamente.

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 lo siento, esta es una respuesta duplicada. – Synesso

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

Si su entrada es Int o Double, puede hacerlo de esta manera:

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

Uso:

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... 

De lo contrario, es posible utilizar BigDecimals. Son lentos, pero vienen con la escala, por lo que "1", "1.0" y "1,00" son todos diferentes:

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

Eso es horrible. Acabas de arrojar todo tipo de seguridad por la ventana. La forma más fácil es hacer: n.toInt.toString – juancn

+4

@juancn ¿Cómo arrojé el tipo de protección por la ventana? Por cierto, "' var n = 1.0; n.toInt.toString' "produce' 1', no '1.0' como se desee. –

+2

La cuestión es que en 'fmt' estás diciendo que aceptas 'Cualquiera', lo que de hecho no es cierto, porque lanzas una IllegalArgumentException si paso, digamos, una Cadena. Podría hacer algo como: 'def fmt [T <% math.ScalaNumericConversions] (n: T) = if (n.toInt == n) n.toInt.toString else n.toString' que es seguro. Las excepciones de argumentos ilegales se deben lanzar solo si el sistema de tipos no puede expresar un conjunto razonable de restricciones (por ejemplo, scala no permite especificar enteros a distancia como tipos). – juancn

4

El uso de un "_.0" al final del punto flotante números es una convención. Solo una forma de saber que el número es realmente un punto flotante y no un número entero.

Si realmente necesita "imprimir de la misma forma en que lo lee", es posible que tenga que replantearse la forma en que se estructura el código, posiblemente conservando los datos de entrada.Si es sólo un problema de formato, la forma más fácil es convertir los valores a números enteros antes de imprimir:

val x = 1.0 
println(x.toInt) 

Si algunos son números enteros y algunos no lo son, se necesita un código de poco más:

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)) 

el código anterior debe imprimir:

1 
1.5 
1 

la firma del método fmt acepta cualquier tipo que, o bien es un subtipo de ScalaNumericConversions o se puede convertir en uno a través de conversiones implícitas (para que podamos usar el método toInt).

2

A partir de 2,10 Scala puede utilizar 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 
Cuestiones relacionadas