How to convert String to Long in Kotlin? - kotlin

So, due to lack of methods like Long.valueOf(String s) I am stuck.
How to convert String to Long in Kotlin?

1. string.toLong()
Parses the string as a [Long] number and returns the result.
#throws NumberFormatException if the string is not a valid
representation of a number.
2. string.toLongOrNull()
Parses the string as a [Long] number and returns the result or null
if the string is not a valid representation of a number.
3. string.toLong(10)
Parses the string as a [Long] number and returns the result.
#throws NumberFormatException if the string is not a valid
representation of a number.
#throws IllegalArgumentException when
[radix] is not a valid radix for string to number conversion.
public inline fun String.toLong(radix: Int): Long = java.lang.Long.parseLong(this, checkRadix(radix))
4. string.toLongOrNull(10)
Parses the string as a [Long] number and returns the result or null
if the string is not a valid representation of a number.
#throws IllegalArgumentException when [radix] is not a valid radix for string
to number conversion.
public fun String.toLongOrNull(radix: Int): Long? {...}
5. java.lang.Long.valueOf(string)
public static Long valueOf(String s) throws NumberFormatException

String has a corresponding extension method:
"10".toLong()

Extension methods are available for Strings to parse them into other primitive types. Examples below:
"true".toBoolean()
"10.0".toFloat()
"10.0".toDouble()
"10".toByte()
"10".toShort()
"10".toInt()
"10".toLong()

Note: Answers mentioning jet.String are outdated. Here is current Kotlin (1.0):
Any String in Kotlin already has an extension function you can call toLong(). Nothing special is needed, just use it.
All extension functions for String are documented. You can find others for standard lib in the api reference

Actually, 90% of the time you also need to check the 'long' is valid, so you need:
"10".toLongOrNull()
There is an 'orNull' equivalent for each 'toLong' of the basic types, and these allow for managing invalid cases with keeping with the Kotlin? idiom.

It's interesting. Code like this:
val num = java.lang.Long.valueOf("2");
println(num);
println(num is kotlin.Long);
makes this output:
2
true
I guess, Kotlin makes conversion from java.lang.Long and long primitive to kotlin.Long automatically in this case. So, it's solution, but I would be happy to see tool without java.lang package usage.

In Kotlin, to convert a String to Long (that represents a 64-bit signed integer) is simple.
You can use any of the following examples:
val number1: Long = "789".toLong()
println(number1) // 789
val number2: Long? = "404".toLongOrNull()
println("number = $number2") // number = 404
val number3: Long? = "Error404".toLongOrNull()
println("number = $number3") // number = null
val number4: Long? = "111".toLongOrNull(2) // binary
println("numberWithRadix(2) = $number4") // numberWithRadix(2) = 7
With toLongOrNull() method, you can use let { } scope function after ?. safe call operator.
Such a logic is good for executing a code block only with non-null values.
fun convertToLong(that: String) {
that.toLongOrNull()?.let {
println("Long value is $it")
}
}
convertToLong("123") // Long value is 123

One good old Java possibility what's not mentioned in the answers is java.lang.Long.decode(String).
Decimal Strings:
Kotlin's String.toLong() is equivalent to Java's Long.parseLong(String):
Parses the string argument as a signed decimal long. ... The
resulting long value is returned, exactly as if the argument and the
radix 10 were given as arguments to the parseLong(java.lang.String, int) method.
Non-decimal Strings:
Kotlin's String.toLong(radix: Int) is equivalent to Java's eLong.parseLong(String, int):
Parses the string argument as a signed long in the radix specified by
the second argument. The characters in the string must all be digits of the specified radix ...
And here comes java.lang.Long.decode(String) into the picture:
Decodes a String into a Long. Accepts decimal, hexadecimal, and octal
numbers given by the following grammar: DecodableString:
(Sign) DecimalNumeral | (Sign) 0x HexDigits | (Sign) 0X HexDigits | (Sign) # HexDigits | (Sign) 0 OctalDigits
Sign: - | +
That means that decode can parse Strings like "0x412", where other methods will result in a NumberFormatException.
val kotlin_toLong010 = "010".toLong() // 10 as parsed as decimal
val kotlin_toLong10 = "10".toLong() // 10 as parsed as decimal
val java_parseLong010 = java.lang.Long.parseLong("010") // 10 as parsed as decimal
val java_parseLong10 = java.lang.Long.parseLong("10") // 10 as parsed as decimal
val kotlin_toLong010Radix = "010".toLong(8) // 8 as "octal" parsing is forced
val kotlin_toLong10Radix = "10".toLong(8) // 8 as "octal" parsing is forced
val java_parseLong010Radix = java.lang.Long.parseLong("010", 8) // 8 as "octal" parsing is forced
val java_parseLong10Radix = java.lang.Long.parseLong("10", 8) // 8 as "octal" parsing is forced
val java_decode010 = java.lang.Long.decode("010") // 8 as 0 means "octal"
val java_decode10 = java.lang.Long.decode("10") // 10 as parsed as decimal

If you don't want to handle NumberFormatException while parsing
var someLongValue=string.toLongOrNull() ?: 0

Actually, there are several ways:
Given:
var numberString : String = "numberString"
// number is the Long value of numberString (if any)
var defaultValue : Long = defaultValue
Then we have:
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString is a valid number ? | true | false |
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString.toLong() | number | NumberFormatException |
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString.toLongOrNull() | number | null |
+—————————————————————————————————————————————+——————————+———————————————————————+
| numberString.toLongOrNull() ?: defaultValue | number | defaultValue |
+—————————————————————————————————————————————+——————————+———————————————————————+

string.toLong()
where string is your variable.

Related

Most idiomatic way to convert a Float value to a string without a decimal point in Kotlin

I'd like to convert a Float value to a String, but without a decimal point. For example, for the following code:
fun toDecimalString(value: Float): String {
// TODO
}
fun main() {
println("Result: ${toDecimalString(1.0f)}")
println("Result: ${toDecimalString(1.999999f)}")
println("Result: ${toDecimalString(20.5f)}")
}
I'd like the expected output to be:
1
1
20
As #Tenfour04 said, the answer is to first convert to an integer, by using .toInt(), which only leaves the digits left of the decimal point, and then convert to string using .toString().
.toInt().toString()
By converting to an Int before turning the input to a string, all decimal point values are dropped, e.g.:
fun toDecimalString(value: Float): String = "${value.toInt()}"

Is it valid to use readLine()!! without adding toInt() if the input is an Int?

Sorry for this dumb question:
It says readLine()!! reads line as a string, but if I enter an integer without adding .toInt(), it runs fine?:
Sample input: 55
fun main() {
println("Enter any number here: ")
val a = readLine()!!
print(a)
}
//prints 55
I am a bit confused, because it prints 55 without any issues. So, readLine()!! can read any type of data and return 55, even if it's not a String?
Actually the 55 you entered is a string and it was printed as string representation also. You couldn't use the 55 to do arithmetic computation eg. 55 - 10 without make it as integer or other number representation like double.
You can check the type like this
if (a is String) {
print("It's string")
}

scanner in kotlin to read in 2 lines

Here is the code. n continually outputs 50 and not 2:
import java.util.*
fun main(args: Array<String>) {
val scanner = Scanner(System.`in`)
val n = scanner.next().first().toInt()
val array1 = readLine()!!.split(" ").map { it.toInt() }
var product:Int=0
println(n)
println(array1[0])
println(array1[1])
if (n ==2) {
product = array1[0] * array1[1]
}
println(product)
}
Sample Input:
2
5 3
Output:
2
5 3
50
5
3
0
How do I use scanner in kotlin to read in 2 lines?
Short form
Use scanner.nextInt() instead of scanner.next().first().toInt().
Explanation
By calling scanner.next() you receive the next complete token of the Scanner as a String. Then you take the first character using first(). The problem is, that calling toInt() on a Char will not parse the string as an integer value but return the ASCII char code of the char.
Example: '2'.toInt() returns 50 and not 2 since the ASCII char code of 2 is 50. (See https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html)
Conclusion: In your case, directly read the integer value from the Scanner using scanner.nextInt(), but if you want to convert a char to an integer by "parsing", convert it to a string first: '2'.toString().toInt() will return an integer with the value 2
Addition
It is probably nice to know that you can also use this the other way round: 50.toChar() returns a character with the value '2'.
👍

How to convert digit to character in Kotlin?

I'm trying to find the simplest way to convert a digit (0..9) into the respective character '0'..'9' in Kotlin.
My initial attempt was to write the following code:
fun convertToCharacter() {
val number = 0
val character = number.toChar()
println(character)
}
Of course, after running, I quickly saw that this produces \u0000, and not '0' like I expected. Then, remembering from how to do this in Java, I modified the code to add '0', but then this would not compile.
fun convertToCharacter() {
val number = 0
val character = number.toChar() + '0'
println(character)
}
What is the appropriate way to convert a number into its respective character counterpart in Kotlin? Ideally, I'm trying to avoid pulling up the ASCII table to accomplish this (I know I can add 48 to the number since 48 -> '0' in ASCII).
val character = '0' + number
is the shortest way, given that the number is in range 0..9
Kotlin stdlib provides this function since 1.5.0.
fun Int.digitToChar(): Char
Returns the Char that represents this decimal digit. Throws an exception if this value is not in the range 0..9.
If this value is in 0..9, the decimal digit Char with code '0'.code + this is returned.
Example
println(5.digitToChar()) // 5
println(3.digitToChar(radix = 8)) // 3
println(10.digitToChar(radix = 16)) // A
println(20.digitToChar(radix = 36)) // K
Like you said, probably the easiest way to convert an Int to the Char representation of that same digit is to add 48 and call toChar():
val number = 3
val character = (number + 48).toChar()
println(character) // prints 3
If you don't want to have the magic 48 number in your program, you could first parse the number to a String and then use toCharArray()[0] to get the Char representation:
val number = 3
val character = number.toString().toCharArray()[0]
println(character) // prints 3
Edit: in the spirit of the attempt in your question, you can do math with '0'.toInt() and get the result you were expecting:
val number = 7
val character = (number + '0'.toInt()).toChar()
println(number) // prints 7
How about 0.toString() instead of 0.toChar() ? If you are specifically after single digits, then 0.toString()[0] will give you a Char type
You can use an extension like this:
fun Int.toReadableChar(): Char {
return ('0'.toInt() + this).toChar()
}
You can apply this to any other class you want :)
Example:
println(7.toReadableChar())
>> 7

Why single char and "single char String" not equal when converted to long (.toLong())

I wanted to sum the digits of Long variable and add it to the variable it self, I came with the next working code:
private fun Long.sumDigits(): Long {
var n = this
this.toString().forEach { n += it.toString().toLong() }
return n
}
Usage: assert(48.toLong() == 42.toLong().sumDigits())
I had to use it.toString() in order to get it work, so I came with the next test and I don't get it's results:
#Test
fun toLongEquality() {
println("'4' as Long = " + '4'.toLong())
println("\"4\" as Long = " + "4".toLong())
println("\"42\" as Long = " + "42".toLong())
assert('4'.toString().toLong() == 4.toLong())
}
Output:
'4' as Long = 52
"4" as Long = 4
"42" as Long = 42
Is it a good practice to use char.toString().toLong() or there is a better way to convert char to Long?
Does "4" represented by chars? Why it is not equal to it char representation?
From the documentation:
class Char : Comparable (source) Represents a 16-bit Unicode
character. On the JVM, non-nullable values of this type are
represented as values of the primitive type char.
fun toLong(): Long
Returns the value of this character as a Long.
When you use '4' as Long you actually get the Unicode (ASCII) code of the char '4'
As mTak says, Char represents a Unicode value. If you are using Kotlin on the JVM, you can define your function as follows:
private fun Long.sumDigits() = this.toString().map(Character::getNumericValue).sum().toLong()
There's no reason to return Long rather than Int, but I've kept it the same as in your question.
Non-JVM versions of Kotlin don't have the Character class; use map {it - '0'} instead.