37

Just can't find a way to transform an Hex String to a number (Int, Long, Short) in Scala.

Is there something like "A".toInt(base)?

5 Answers 5

54

You can use the Java libs:

val number = Integer.parseInt("FFFF", 16)
> number: Int = 65535

Or if you are feeling sparky :-):

implicit def hex2int (hex: String): Int = Integer.parseInt(hex, 16)

val number: Int = "CAFE" // <- behold the magic
number: Int = 51966

Also, if you aren't specifically trying to parse a String parameter into hex, note that Scala directly supports hexadecimal Integer literals. In this case:

val x = 0xCAFE
> x: Int = 51966

Isn't Scala wonderful? :-)

5
  • 2
    Hahah, mind block! You are right. Anyway, with Integer scala 2.9 resolves the parseInt method but with Short and Long don't. Any ideas?
    – rsan
    Commented May 26, 2012 at 5:10
  • 2
    I think "Short" is resoling to Scala's Short. This works: val x = java.lang.Short.parseShort("FF", 16) // x: Short = 255
    – 7zark7
    Commented May 26, 2012 at 5:15
  • 5
    Came here when googling for the opposite, converting int to str. For the record: That is Integer.toString(number, base) or BigInt(number).toString(base), if you happen to have a bigint. (but doesn't work with bases above 36, very annoying)
    – BeniBela
    Commented Sep 30, 2012 at 10:20
  • How do you go to Long (since that's in the question Google takes you here)? Commented Jan 9, 2017 at 20:08
  • 1
    java.lang.Long.parseLong("CAFE", 16)
    – 7zark7
    Commented Jan 14, 2017 at 7:12
31

7zark7 answer is correct, but I want to make some additions. Implicit from String to Int can be dangerous. Instead you can use implicit conversion to wrapper and call parsing explicitly:

class HexString(val s: String) {
    def hex = Integer.parseInt(s, 16)
}
implicit def str2hex(str: String): HexString = new HexString(str)

val num: Int = "CAFE".hex
2
  • 1
    Indeed, that implicit conversion sounded error prone. But this way you have fexibility and clarity at the same time. Thanx
    – rsan
    Commented May 26, 2012 at 23:34
  • 1
    You could just do the same with an implicit class: implicit class StringToHexStringAugmenter(val s: String) { def hex(): Int = Integer.parseInt(s, 16) } Less code for the same thing Commented Aug 31, 2016 at 14:03
12

What about a one-liner?

def hexToInt(s: String): Int = {
    s.toList.map("0123456789abcdef".indexOf(_)).reduceLeft(_ * 16 + _)
}

scala> hexToInt("cafe")
res0: Int = 51966

And to answer your second item:

Is there something like "A".toInt(base)?

Yes, still as a one-liner:

def baseToInt(s: String, base: String): Int = {
    s.toList.map(base.indexOf(_)).reduceLeft(_ * base.length + _)
}

scala> baseToInt("1100", "01")
res1: Int = 12
0
7

Anyone wanting to convert a UUID from hex to a decimal number can borrow from Benoit's answer and use BigDecimal for the job:

scala> "03cedf84011dd11e38ff0800200c9a66".toList.map(
 |   "0123456789abcdef".indexOf(_)).map(
 |     BigInt(_)).reduceLeft( _ * 16 + _)
res0: scala.math.BigInt = 5061830576017519706280227473241971302

Or more generally:

def hex2dec(hex: String): BigInt = {
  hex.toLowerCase().toList.map(
    "0123456789abcdef".indexOf(_)).map(
    BigInt(_)).reduceLeft( _ * 16 + _)
}

def uuid2dec(uuid: UUID): BigInt = {
  hex2dec(uuid.toString.replace("-",""))
}

Then:

scala> import java.util.UUID

scala> val id = UUID.fromString("3CEDF84-011D-D11E-38FF-D0800200C9A66")
id: java.util.UUID = 03cedf84-011d-d11e-38ff-0800200c9a66

scala> uuid2dec(id)
res2: BigInt = 5061830576017519706280227473241971302

One practical application for this is encoding the UUID in a barcode, where Code128 produces a shorter barcode for all digits than it does with alphanumeric strings. See notes about subtype "128A" on http://en.wikipedia.org/wiki/Code128#Subtypes.

5

For Long and Short, it is also possible to use the Java methods directly like

Long2long(java.lang.Long.valueOf(hexString, 16))

where Long2long can be even be omitted in some cases.

Not the answer you're looking for? Browse other questions tagged or ask your own question.