How to convert Int to Hex String in Kotlin? - numbers

I'm looking for a similar function to Java's Integer.toHexString() in Kotlin. Is there something built-in, or we have to manually write a function to convert Int to String?

You can still use the Java conversion by calling the static function on java.lang.Integer:
val hexString = java.lang.Integer.toHexString(i)
And, starting with Kotlin 1.1, there is a function in the Kotlin standard library that does the conversion, too:
fun Int.toString(radix: Int): String
Returns a string representation of this Int value in the specified radix.
Note, however, that this will still be different from Integer.toHexString(), because the latter performs the unsigned conversion:
println((-50).toString(16)) // -32
println(Integer.toHexString(-50)) // ffffffce
But with experimental Kotlin unsigned types, it is now possible to get the same result from negative number unsigned conversion as with Integer.toHexString(-50):
println((-50).toUInt().toString(16)) // ffffffce

You can simply do it like this:
"%x".format(1234)

If you need to add zero before bytes which less than 10(hex), for example you need string - "0E" then use:
"%02x".format(14)

Related

Why can I concatenate String and Int in Scala?

I'm trying out some things in Scala, coming from Python. Since Scala is a lot more strict about keeping types consistent, I was surprised to find out that I can do the following concatenation, which would blow up in Python:
def adder(one:Any, two:String) = {one+two}
adder("word", "suffix")
res13: String = wordsuffix
But also:
val x:Int = 1
adder(x, "suffix")
res12: String = 1suffix
So it just transforms an Int into a String w/out telling me. What is this called and what is the logic behind it?
And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.
I know this is not very specific and if this is too broad, I'll gladly retract the question.
There is an implicit class in scala.Predef that operates on objects of any type
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}
That implements Any + String (as you have defined it in adder). As rogue-one mentioned, there is also a method for concatenating String + Any defined in StringOps. If you tried to do Any + Any it would fail because it's expecting a String as the argument.
So it just transforms an Int into a String w/out telling me
Scala is converting your Int into a String, but it's not a type conversion because Int cannot be coerced into a String. You can observe that by trying something like this:
def foo(str: String) = ???
foo(5) // Type mismatch: expected: String, actual: Int
That will fail to compile because Scala can't magically coerce an Int into a String.
what is the logic behind it?
See implicit classes
And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.
It's a convenience method that's very specific to String and concatenation. This feature is implemented in Java, so I believe it was implemented in Scala to maintain source compatibility. My example above shows that (except in this specific case), user input to a function will respect the types defined on the function.
It's called implicit conversion (or implicit typecasting)
The purpose - convenience so you don't have to do everything manually. Most high-level languages will do that with the most used generics like strings, ints, bools...
You can check scala.Predef to see all the methods used when implicitly converting types, and you can take control of it using scala.language.implicitConversions. Read more at Scala Documentation.
This String concatenation not only works for Int but for any data-type. For instance
scala> case class Elephant(value: String)
defined class Elephant
scala> "Hello" + Elephant("elephant")
res2: String = HelloElephant(elephant)
This is because of the method + defined in StringOps (via Predef) class that accepts argument of type Any. So it is a method that is made available to a String object via implicit conversion that takes an argument of type Any. so "Hello" + Elephant("elephant") is actually "Hello".+(Elephant("elephant"))

scala 2.10 - Stringbuilder constructor not working

I came across this issue when I was trying to form strings build with Integers. I used scala's Stringbuilder and see this weird behavior.
println(new StringBuilder(1).append(2).append(3))
>23
println(new StringBuilder(1.toString()).append(2).append(3))
>123
Am I doing something wrong or just implicit conversion not taking place in constructor argument and ignores it silently.
The constructor takes an Int for starting capacity, which is why you don't see it as output in your string:
def this(capacity: Int) = this(capacity, "")
You are using 2 different constructors:
StringBuilder(int capacity): Constructs a string builder with no characters in it and an initial capacity specified by the capacity argument.
StringBuilder(String str): Constructs a string builder initialized to the contents of the specified string.
So new StringBuilder(1) returns an empty new StringBuilder of initial capacity 1.

How to write binary literals in Scala?

Scala has direct support for using hex and octal numbers:
scala> 01267 + 0100
res1: Int = 759
scala> 0x12AF + 0x100
res2: Int = 5039
but how do you do express an integer as a binary number in Scala ?.
If performance is not an issue, you can use a String and convert it to an integer.
val x = Integer.parseInt("01010101", 2)
Binary numbers aren't supported directly in part because you can easily convert from hexadecimal to binary and vice versa. To make your code clearer, you can put the binary number in a comment.
val x = 0x55 //01010101
In 2.10 you can create a string interpolator for that, e.g. it's possible to write b"0010" to mean 2. Using macros you can get rid of associated runtime overhead and do the conversion at compile-time. Take a look at Jason Zaugg's macrocosm to see it in action:
scala> b"101010"
res4: Int = 42
scala> b"102"
<console>:11: error: exception during macro expansion: invalid binary literal
b"102"
^
Using the new "implicit class" and "value class" mechanisms in 2.10, you can write something like this to add convenience methods without the overhead of object creation:
implicit class IntToBase( val digits:String ) extends AnyVal {
def base(b:Int) = Integer.parseInt( digits, b )
def b = base(2)
def o = base(8)
def x = base(16)
}
That allows you to do things like
"555".o // 365 decimal
and no IntToBase object is ever actually created.
You would need to be careful if you're converting from an integer that "looks like" binary as #agilesteel suggests. For example 0101.b would try to convert 65 decimal to binary (initial 0 signifying octal), whereas 101.b would try to convert 101 decimal to binary. It only really makes sense to try to convert from a String, for which there is Integer.parseInt, and from a number to the binary String representation, for which there is Integer.toString(x, 2).
I can't think of too many use-cases for programmatic binary literals. That said, they've made it to Java 7 as a number with prefix 0b, so I'd be surprised if they didn't appear in Scala soon. Java seems to have done fine without them for 15 years though.
If you are planning on using it a lot you can simulate the behavior with an implicit conversion.
object Extensions {
implicit def conversion(x: Int) = new BinaryInt(x)
class BinaryInt(x: Int) {
def b = {
// Conversion code like Integer.parseInt
// as Kim suggested
}
}
}
Now you can do stuff like
import Extensions._
val x = 0101.b
// or
val x = 5.b
You have to decide for yourself, which direction the conversion should go.
If you want to get a string of the binary representation of an Int you can call 4.toBinaryString. Padding is more difficult. You'll have to do something like: 4.toBinaryString.reverse.padTo(8, "0").reverse.mkString
def _0b(row: Int): Int = {
row.toString
.reverse
.split("")
.zipWithIndex
.map(x => (x._1.toInt, x._2))
.filter(_._1 == 1)
.map(x => Math.pow(2,x._2).toInt)
.sum
}
_0b(10011001) = 153
Though it is limited to 32Bit Values

How to unimport String "+" operator in Scala?

I'm writing a DSL where the "+" operator is strictly numeric, like some other popular languages. It's close, but the String "+" operator is messing up my implicit conversions. What's the syntax for unimporting an operator of the String class?
Just to be clearer, instead of this:
scala> var x = "2" + 3;
x: java.lang.String = 23
I'd like to get x: Int = 5
I imagine I just need 2 things to make that happen:
Remove (unimport within my scope) the definition of "+" from Strings
Define an implicit conversion of String to Int
I'm stuck on the first step.
Thanks
According to section 12.3.1 of the Scala spec, the + method for String has special treatment by the compiler. I don't know for sure, but I think this means you can't "unimport" it, which is a shame because it really breaks the type system (much like the related toString method).
Could you use a different name for the operator in your DSL, eg, ++ or &?
The + method for a string is a method on of the String class (and therefore on each string object), and as such it cannot be unimported.
You can't unimport it, but you could use +: and define it on the int class. What would be best is if you write it like this: "2".toInt + 3.

What is the differences between Int and Integer in Scala?

I was working with a variable that I had declared as an Integer and discovered that > is not a member of Integer. Here's a simple example:
scala> i
warning: there were deprecation warnings; re-run with -deprecation for details
res28: Integer = 3
scala> i > 3
<console>:6: error: value > is not a member of Integer
i > 3
^
Compare that to an Int:
scala> j
res30: Int = 3
scala> j > 3
res31: Boolean = false
What are the differences between Integer and Int? I see the deprecation warning but it's unclear to me why it was deprecated and, given that it has been, why it doesn't have a > method.
"What are the differences between Integer and Int?"
Integer is just an alias for java.lang.Integer. Int is the Scala integer with the extra capabilities.
Looking in Predef.scala you can see this the alias:
/** #deprecated use <code>java.lang.Integer</code> instead */
#deprecated type Integer = java.lang.Integer
However, there is an implicit conversion from Int to java.lang.Integer if you need it, meaning that you can use Int in methods that take an Integer.
As to why it is deprecated, I can only presume it was to avoid any confusion over which kind of integer you were working with.
Integer gets imported from java.lang.Integer and is only for compatibility with Java. Since it is a Java class, of course it can't have a method called "<".
EDIT: You can mitigate this problem by declaring an implicit conversion from Integer to Int.
implicit def toInt(in:Integer) = in.intValue()
You'll still get deprecation warning though.
I think the problem you're seeing has has to do boxing/unboxing of value types and the use of the Java class Integer.
I think the answer is here: Boxing and unboxing in Scala. There is no implict unboxing in Scala. You've defined i as the Java class Integer but in the i > 3, the 3 is being treated and an int.
Integer is a Java class, java.lang.Integer. It's different from Java's primitive type int, which is not a class. It can't have < defined, because Java does not allow operators to be defined for classes.
Now, you might wonder why such a type exist at all? Well, primitive types cannot be passed as references, so you can't pass an int to a method expecting java.lang.Object, equivalent to Scala's AnyRef, for example. To do that, you put that int inside an Integer object, and then pass the Integer.
Integer gets imported from java.lang.Integer and is only for compatibility with Java. Since it is a Java class, of course it can't have a method called "<".
EDIT: You can mitigate this problem by declaring an implicit conversion from Integer to Int.