In Scala, I can't seem to convert hex-strings back to integers:
val cols = Array(0x2791C3FF, 0x5DA1CAFF, 0x83B2D1FF, 0xA8C5D8FF,
0xCCDBE0FF, 0xE9D3C1FF, 0xDCAD92FF, 0xD08B6CFF,
0xC66E4BFF, 0xBD4E2EFF)
cols.map({ v => Integer.toHexString(v)}).map(v => Integer.parseInt(v, 16))
I get the following error message:
java.lang.NumberFormatException: For input string: "83b2d1ff"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:583)
at $anonfun$3.apply(<console>:12)
at $anonfun$3.apply(<console>:12)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.mutable.ArrayOps$ofRef.map(ArrayOps.scala:186)
... 35 elided
Int is too small. Use Long.
scala> 0x83B2D1FFDL
res3: Long = 35352551421
or
scala> java.lang.Long.decode("0x83B2D1FFD")
res4: Long = 35352551421
and back
scala> java.lang.Long.toHexString(res3)
res5: String = 83b2d1ffd
Try it as unsigned values.
cols.map(Integer.toHexString).map(Integer.parseUnsignedInt(_, 16))
Related
I am receiving the following error:
Exception in thread "main" java.lang.IndexOutOfBoundsException: -1
at scala.collection.immutable.Vector.checkRangeConvert(Vector.scala:132)
at scala.collection.immutable.Vector.apply(Vector.scala:122)
This means that I am out of memory?
How can i fix it?
you get IndexOutOfBoundsException, when you try to access an index greater than number of elements in a collection or less than 0 as the vector starts from index 0.
example below,
scala> val vector = Vector("washington", "iowa", "california")
vector: scala.collection.immutable.Vector[String] = Vector(washington, iowa, california)
scala> vector(0)
res4: String = washington
scala> vector(1)
res5: String = iowa
scala> vector(2)
res6: String = california
you get IndexOutOfBoundsException if you try to access index < 0 or index >=3,
scala> vector(3)
java.lang.IndexOutOfBoundsException: 3
at scala.collection.immutable.Vector.checkRangeConvert(Vector.scala:132)
at scala.collection.immutable.Vector.apply(Vector.scala:122)
... 33 elided
how can i fix it?
check if the index you are accessing is lesser than 0 or greater than number of elements in a vector or use .lift on collection.
scala> vector.lift(0)
res14: Option[String] = Some(washington)
scala> vector.lift(3)
res15: Option[String] = None
releated question - How to get an Option from index in Collection in Scala?
You are trying to access the -1th element of your vector. In Scala there are not circular indexes like in some other languages, so you are only allowed to specify positive indexes (and zero). Here is an example:
val v = Vector("a", "b", "c")
v: scala.collection.immutable.Vector[String] = Vector(a, b, c)
scala> v(0)
res1: String = a
scala> v(1)
res2: String = b
scala> v(-1)
java.lang.IndexOutOfBoundsException: -1
at scala.collection.immutable.Vector.checkRangeConvert(Vector.scala:123)
at scala.collection.immutable.Vector.apply(Vector.scala:114)
As you can see, when I specify the indexes 0 or 1 everything is fine, but when I try -1 I get the same error you are seeing. The error not in how you are accessing the vector, but the part of the vector you are trying to access.
In this code where I'm attempting to xor the corresponding characters of two strings :
val s1 = "1c0111001f010100061a024b53535009181c";
val s2 = "686974207468652062756c6c277320657965";
val base64p1 = Base64.getEncoder().encodeToString(new BigInteger(s1, 16).toByteArray())
val base64p2 = Base64.getEncoder().encodeToString(new BigInteger(s2, 16).toByteArray())
val zs : IndexedSeq[(Char, Char)] = base64p1.zip(base64p2);
val xor = zs.foldLeft(List[Char]())((a: List[Char] , b: (Char, Char)) => ((Char)((b._1 ^ b._2))) :: a)
produces error :
Char.type does not take parameters
[error] val xor = zs.foldLeft(List[Char]())((a: List[Char] , b: (Char, Char)) => ((Char)((b._1 ^ b._2))) :: a)
How to xor the corresponding string char values and add them to List ?
What you're doing is can be simplified.
val xor = base64p1.zip(base64p2).map{case (a,b) => (a^b).toChar}.reverse
The result of the XOR op (^) is an Int. Just add .toChar to change it to a Char value.
But it looks like what you really want to do is XOR two large hex values that are represented as strings, and then return the result as a string. To do that all you need is...
val (v1, v2) = (BigInt(s1, 16), BigInt(s2, 16))
f"${v1 ^ v2}%x" // res0: String = 746865206b696420646f6e277420706c6179
You use java casting syntax. In scalla you cast like var.asInstanceOf[Type].
Should be (b._1 ^ b._2).asInstanceOf[Char].
val bb =0
val cc ="%07d"
println(f"$bb$cc") //0%07d
println(f"$bb%07d") //0000000
I expect
println(f"$bb$cc") //0000000
println(f"$bb%07d") //0000000
Why isn't the result the same?
How can I make it the same?
By using f"string" you are declaring that you want to make a formatted string.
with f"$bb$cc" you are using the variables bb and cc, so it accesses the strings for them
with f"$bb%07d" you are telling it to transform bb into a number with 7 decimal places, and 0s if the number isn't large enough
further examples to help understanding:
val bb = 1
println(f"$bb%07d") // 0000001
println(f"$bb%05d") // 00001
val bb = 11
println(f"$bb%05d") //00011
to get the same string, try using s"string"
val bb = 0
println(s"$bb%07d") // 0%07d
to use a string as a formatter:
val cc = "%07d"
val bb = 0
println(cc.format(bb)) //0000000
//for more information http://docs.scala-lang.org/overviews/core/string-interpolation.html
I think that you already know that, but just to be clear:
$ is used for marking of variable references
% is used for formatting the references
Generally you use f interpolator like this: f"$<reference>%<format>"
When you write:
println(f"$bb$cc")
This is what happens:
Parser recognizes $bb with no formatting.
Parser recognizes $cc with no formatting.
Substitutes $bb with 0
Substitutes $bb with "%07d"
But when you write:
println(f"$bb%07d")
This is what happens:
Parser recognizes $bb with formatting 07d
Substitutes $bb with 0 and formats it according to "07d", that is: 7 digits and filling with 0 is number is shorter than 7 digits.
You might have thought of this method as being preprocessing like #define cc "%07d" in C but it's simply not.
I'm not currently aware of a way to store the formatting in a separate string. You might consider using a class-based formatter for doing so.
String interpolation syntax requires a string literal.
The point of the f-interpolator macro is to give compile-time safety.
scala> val x = 0.1
x: Double = 0.1
scala> f"$x"
res0: String = 0.1
scala> f"$x%5.5f"
res1: String = 0.10000
scala> f"$x%5d"
<console>:13: error: type mismatch;
found : Double
required: Int
f"$x%5d"
^
scala> val fmt = "%5d"
fmt: String = %5d
scala> fmt format x
java.util.IllegalFormatConversionException: d != java.lang.Double
at java.util.Formatter$FormatSpecifier.failConversion(Formatter.java:4302)
at java.util.Formatter$FormatSpecifier.printInteger(Formatter.java:2793)
at java.util.Formatter$FormatSpecifier.print(Formatter.java:2747)
at java.util.Formatter.format(Formatter.java:2520)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2940)
at scala.collection.immutable.StringLike$class.format(StringLike.scala:318)
at scala.collection.immutable.StringOps.format(StringOps.scala:29)
... 32 elided
This isn't convenient, but you can decompose the string constants and roll it by hand:
scala> final val fmt = "%5d"
fmt: String("%5d") = %5d
scala> new StringContext("", fmt).f(x)
<console>:14: error: type mismatch;
found : Double
required: Int
new StringContext("", fmt).f(x)
^
or
scala> final val fmt = "%5.5f"
fmt: String("%5.5f") = %5.5f
scala> new StringContext("", fmt).f(x)
res8: String = 0.10000
scala> final val fmt = "%5.5"
fmt: String("%5.5") = %5.5
scala> new StringContext("", fmt + "f").f(x)
res9: String = 0.10000
scala> new StringContext("", fmt + "d").f(x)
<console>:14: error: precision not allowed
new StringContext("", fmt + "d").f(x)
^
scala> final val fmt = "%5"
fmt: String("%5") = %5
scala> new StringContext("", fmt + "d").f(x)
<console>:14: error: type mismatch;
found : Double
required: Int
new StringContext("", fmt + "d").f(x)
^
The error if you try it with non-constant String:
scala> val fmt = "%5d"
fmt: String = %5d
scala> new StringContext("", fmt).f(x)
<console>:14: error: exception during macro expansion:
java.lang.IllegalArgumentException: internal error: argument parts must be a list of string literals
at scala.tools.reflect.FormatInterpolator.scala$tools$reflect$FormatInterpolator$$copyPart$1(FormatInterpolator.scala:82)
at scala.tools.reflect.FormatInterpolator.interpolated(FormatInterpolator.scala:181)
at scala.tools.reflect.FormatInterpolator.interpolate(FormatInterpolator.scala:38)
at scala.tools.reflect.FastTrack$$anonfun$1$$anonfun$apply$5$$anonfun$applyOrElse$5.apply(FastTrack.scala:54)
at scala.tools.reflect.FastTrack$$anonfun$1$$anonfun$apply$5$$anonfun$applyOrElse$5.apply(FastTrack.scala:54)
at scala.tools.reflect.FastTrack$FastTrackEntry.apply(FastTrack.scala:41)
at scala.tools.reflect.FastTrack$FastTrackEntry.apply(FastTrack.scala:36)
at scala.tools.nsc.typechecker.Macros$class.macroExpandWithRuntime(Macros.scala:763)
new StringContext("", fmt).f(x)
^
I can cast Int data to Byte.
scala> 10.asInstanceOf[Byte]
res8: Byte = 10
However with the same value in Any type, the cast raises an error.
scala> val x : Any = 10
x: Any = 10
scala> x.asInstanceOf[Byte]
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Byte
at scala.runtime.BoxesRunTime.unboxToByte(BoxesRunTime.java:98)
at .<init>(<console>:10)
I can cast twice.
scala> val y = x.asInstanceOf[Int]
y: Int = 10
scala> y.asInstanceOf[Byte]
res11: Byte = 10
Are there better ways than this?
In Scala, compiler tries to hide the distinction between primitive types and reference ones (boxed), defaulting to primitives. Sometimes, abstractions leak and you see that kind of problems.
Here, you're pretending that value is Any, which require compiler to fallback to boxed values:
override def set(value:Any) = {
if (check(value.asInstanceOf[Byte])) {
And here, you're not limiting value to be referential, so such casting will be done on primitive types:
10.asInstanceOf[Byte]
In other words:
scala> val x: Any = 10
x: Any = 10
scala> x.asInstanceOf[Byte]
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Byte
at scala.runtime.BoxesRunTime.unboxToByte(BoxesRunTime.java:97)
... 32 elided
scala> val y: Int = 10
y: Int = 10
scala> y.asInstanceOf[Byte]
res4: Byte = 10
To overcome this problem, you probably have to go through an extra conversion to, say, String:
scala> x.toString.toInt
res6: Int = 10
scala> x.toString.toByte
res7: Byte = 10
Try converting to int and then to Byte:
scala> val x : Any = 10
x: Any = 10
scala> x.asInstanceOf[Int].asInstanceOf[Byte]
res1: Byte = 10
Or as IonuČ› G. Stan suggested:
scala> x.asInstanceOf[Int].toByte
res4: Byte = 10
Although I cannot explain why this work.
An integer is 32 bits in Java, while a byte is obviously 8 bits. The problem is what bits do you truncate to make an integer a byte? The least significant 24 bits or the most significant 24 bits? The correct answer is in the context of your problem.
I have a dynamically changing input reading from a file. The numbers are either Int or Double. Why does Scala print .0 after every Double number? Is there a way for Scala to print it the same way it reads it?
Example:
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
I can't use Int because some of the input I get are Doubles. I can't use String or AnyVal because I perform some math operations.
Thank you,
scala> "%1.0f" format 1.0
res3: String = 1
If your input is either Int or Double, you can do it like this:
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...
Otherwise, you might use BigDecimals. They are slow, but they do come with the scale, so "1", "1.0" and "1.00" are all different:
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
var x:Double = 1
var y:Double = 1.0
print(x) // => 1.0
print(y) // => 1.0
If i understand you question you want scala to print x and y differently? The problem is that x and y are both a variable of the type Double and look the same.
Why do you explicitly define the type of the vars?
var x = 1
var y= 1.0
print(x) // => 1
print(y) // => 1.0
Use printf:
printf("The value is %.0f", x)
For a description of the format string, see this page from the Java SE 6 API documentation.
Note that you can ofcourse also use the Java library from Scala, so other ways to format numbers from Java can also be used from Scala. You can for example use class java.text.DecimalFormat:
val df = new java.text.DecimalFormat("#####")
println(df.format(x))
Starting with Scala 2.10 you can use 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
The use of a "_.0" at the end of floating point numbers is a convention. Just a way to know that the number is actually floating point and not an integer.
If you really need to "to print it the same way it reads it" you may have to rethink the way your code is structured, possibly preserving your input data. If it's just a formatting issue, the easiest way is to convert the values to integers before printing:
val x = 1.0
println(x.toInt)
If some are integers and some are not, you need a bit more code:
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))
The code above should print:
1
1.5
1
The signature of the fmt method accepts any type that either is a subtype of ScalaNumericConversions or can be converted to one through implicit conversions (so we can use the toInt method).
If you are working with a Double and want to format it as a String without .0 when it's a whole number and with its decimals otherwise, then you could use String::stripSuffix:
x.toString.stripSuffix(".0")
// val x: Double = 1.34 => "1.34"
// val x: Double = 1.0 => "1"
Use type inference, rather than explicit typing.
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