I want to add commas or point every 3 digit in EditText input.
Example :
input : 1000. Output : 1.000
input : 11000. Output : 11.000
If you are on the JVM you can use
"%,d".format(input)
which gives 11,000 for input 11000. Replace , with any delimiter you require.
If you want to use predefined number formats, e.g. for the current locale, use:
java.text.NumberFormat.getIntegerInstance().format(input);
Be also sure to check the other format instances, e.g. getCurrencyInstance or getPercentInstance. Note that you can use NumberFormat also with other locales. Just pass them to the get*Instance-method.
Some of the second variant can also be found here: Converting Integer to String with comma for thousands
If you are using it via Javascript you may be interested in: How do I format numbers using JavaScript?
Based on Splitframe answer above, did a simplified version (without the var):
fun Int.formatDecimalSeparator(): String {
return toString()
.reversed()
.chunked(3)
.joinToString(",")
.reversed()
}
And added some tests:
#Test
fun whenFormatDecimal_thenReturnFormatted() {
mapOf(
1 to "1",
12 to "12",
123 to "123",
1234 to "1,234",
12345 to "12,345",
123456 to "123,456",
1234567 to "1,234,567",
12345678 to "12,345,678",
123456789 to "123,456,789",
1234567890 to "1,234,567,890",
).forEach { (test, expected) ->
val result = test.formatDecimalSeparator()
assertEquals(expected, result)
}
}
In my case is a KMM project, and we don't support other languages, so it does the job. A better solution I would say to create an expect Util class and each platform implement the formatter taking account of the user Locale, etc.
System.out.println(NumberFormat.getNumberInstance(Locale.US).format(35634646));
This is a simple way that able you to replace default separator with any characters:
val myNumber = NumberFormat.getNumberInstance(Locale.US)
.format(123456789)
.replace(",", "،")
I used this for a non JVM Kotlin environment:
fun formatDecimalSeperators(number :String) :String {
var index = 1
return number
.takeIf { it.length > 3 }
?.reversed()
?.map { if (index++ % 3 == 0) "$it," else it }
?.joinToString("")
?.reversed()
?.removePrefix(",")
?: number
}
You can also use #Roland answer in Android String Resources to format it:
<string name="answer_count">%,01d answers</string>
For a method without getting Locale, you can use an extension to convert your Int into a formatted String like this below :
fun Int.formatWithThousandComma(): String {
val result = StringBuilder()
val size = this.toString().length
return if (size > 3) {
for (i in size - 1 downTo 0) {
result.insert(0, this.toString()[i])
if ((i != size - 1) && i != 0 && (size - i) % 3 == 0)
result.insert(0, "\'")
}
result.toString()
} else
this.toString()
}
Related
Ex 10.0 = 10
10.3 = 10.3
10.7 = 10. 7
Looking for a convenient way from Kotlin Standard library
You can use the following function:
fun removeTrailingZeros(num: String): String {
if(!num.contains('.')) // Return the original number if it doesn't contain decimal
return num
return num
.dropLastWhile { it == '0' } // Remove trailing zero
.dropLastWhile { it == '.' } // Remove decimal in case it's the last character in the resultant string
}
You can verify the code here
You can try this:
double number = 23.471;
if (number % 1 != 0)
{
//round off here
System.out.print ("Decimal");
}
else
{
System.out.print ("Integer");
}
If you want to get a string, the easiest way is to work with a string like num.toString().replace(".0",""). For numbers conversion does not make sense since the resulting type is different for different inputs.
Is there a simple way to check if user's input is numeric? Using regexes and exceptions seems too complicated here.
fun main {
val scan = Scanner(System.`in`)
val input = scanner.nextLine()
if (!input.isNumeric) {
println("You should enter a number!")
}
}
The method mentioned above will work for a number <= approximately 4*10^18 essentially max limit of Double.
Instead of doing that since String itself is a CharSequence, you can check if all the character belong to a specific range.
val integerChars = '0'..'9'
fun isNumber(input: String): Boolean {
var dotOccurred = 0
return input.all { it in integerChars || it == '.' && dotOccurred++ < 1 }
}
fun isInteger(input: String) = input.all { it in integerChars }
fun main() {
val input = readLine()!!
println("isNumber: ${isNumber(input)}")
println("isInteger: ${isInteger(input)}")
}
Examples:
100234
isNumber: true
isInteger: true
235.22
isNumber: true
isInteger: false
102948012120948129049012849102841209849018
isNumber: true
isInteger: true
a
isNumber: false
isInteger: false
Its efficient as well, there's no memory allocations and returns as soon as any non-satisfying condition is found.
You can also include check for negative numbers by just changing the logic if hyphen is first letter you can apply the condition for subSequence(1, length) skipping the first character.
joining all the useful comments and putting it in a input stream context, you can use this for example:
fun readLn() = readLine()!!
fun readNumericOnly() {
println("Enter a number")
readLn().toDoubleOrNull()?.let { userInputAsDouble ->
println("user input as a Double $userInputAsDouble")
println("user input as an Int ${userInputAsDouble.toInt()}")
} ?: print("Not a number")
}
readNumericOnly()
for input: 10
user input as a Double 10.0
user input as an Int 10
for input: 0.1
user input as a Double 0.1
user input as an Int 0
for input: "word"
Not a number
Simply use : text.isDigitsOnly() in kotlin.
Well all the answers here are best suited for their own scenarios:
But not all string are numeric digits it can have (-) and (.) decimal pointers.
So to accomplish this I made a cocktail of all the answers suggested below and from other posts as well which - looks like below :
fun isPosOrNegNumber(s: String?) : Boolean {
return if (s.isNullOrEmpty()) false
else{
if(s.first()=='-' && s.filter { it == '.' }.count() <= 1) {
s.removeRange(0,1).replace(".","").all{Character.isDigit(it)}
}
else s.all {Character.isDigit(it)}
}
}
Above code does a good job for its purpose.
But then it struck me kotlin does an even better job with matching a regex and voila the solution became simple and elegant as below :
fun isPosOrNegNumber(s: String?) : Boolean {
val regex = """^(-)?[0-9]{0,}((\.){1}[0-9]{1,}){0,1}$""".toRegex()
return if (s.isNullOrEmpty()) false
else regex.matches(s)
}
This sample regex is only for US number formats but if you want to use EU number formats then just replace '.' with ','
Bdw. if the numbers contain commas then just replace it while sending to this method or better form a regex pattern with commas in it.
Another way to check if the given string is numeric( to check for both negative and positive values ) or not:
val intChars = '0'..'9'
fun isNumeric(input: String) = input
.removePrefix("-")
.all { it in '0'..'9' }
A simple answer without any custom functions is to utilise toDoubleOrNull function. If it returns null, the string is not numeric.
val string = "-12345.666"
if (string.toDoubleOrNull()!=null) // string is numeric
{
//do something
}
If you know the input only contains integers you can also use toIntOrNull likewise
I have a double value, if that number is like this: 123.00 I need to show it as 123 only, without decimal places, but, if the number is like 123.23 or 123.2, I need to show it with the present decimal places: 123.23 or 123.2, as the case may be.
I have tried with decimal format but I couldn't find the right pattern.
It is a better way to do this than a string conversion and operate with substrings and things like that?
DecimalFormat is what you're looking for I think:
import java.text.DecimalFormat
fun main(args : Array<String>) {
val df = DecimalFormat("0.##")
println(df.format(123.0))
println(df.format(123.3))
println(df.format(123.32))
println(df.format(123.327))
}
Output:
123
123.3
123.32
123.33
Here's one way you could do it:
fun func(x: Double): String {
if (x.rem(1).compareTo(0) == 0){
return x.toInt().toString();
} else {
return x.toString();
}
}
print(func(1.32132)); //Returns 1.32132
print(func(3.00)); //Returns 3
You could use DecimalFormat with setMaximumFractionDigits. Creating an extension function would keep the complexity away from the call-site:
fun Double.toStringRounded(fracDigits: Int) = DecimalFormat().apply {
setMaximumFractionDigits(fracDigits)
}.format(this)
Usage:
3.14159.toStringRounded(2) // will be "3.14"
I'd like to use a when() expression in Kotlin to return different values from a function. The input is a String, but it might be parsable to an Int, so I'd like to return the parsed Int if possible, or a String if it is not. Since the input is a String, I cannot use the is type check expression.
Is there any idiomatic way to achieve that?
My problem is what the when() expression should look like, not about the return type.
Version 1 (using toIntOrNull and when as requested)
fun String.intOrString(): Any {
val v = toIntOrNull()
return when(v) {
null -> this
else -> v
}
}
"4".intOrString() // 4
"x".intOrString() // x
Version 2 (using toIntOrNull and the elvis operator ?:)
when is actually not the optimal way to handle this, I only used when because you explicitly asked for it. This would be more appropriate:
fun String.intOrString() = toIntOrNull() ?: this
Version 3 (using exception handling):
fun String.intOrString() = try { // returns Any
toInt()
} catch(e: NumberFormatException) {
this
}
The toIntOrNull function in the kotlin.text package (in kotlin-stdlib) is probably what you're looking for:
toIntOrNull
fun String.toIntOrNull(): Int? (source)
Platform and version requirements: Kotlin 1.1
Parses the string as an Int number and returns the result or null if the string is not a valid representation of a number.
fun String.toIntOrNull(radix: Int): Int? (source)
Platform and version requirements: Kotlin 1.1
Parses the string as an Int number and returns the result or null if the string is not a valid representation of a number.
More information: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/to-int-or-null.html
Using let for one
fun isInteger(str: String?) = str?.toIntOrNull()?.let { true } ?: false
Simple and intuitive
fun isNumeric(str: String) = str.all { it in '0'..'9' }
As #coolMind point out, if you want to filter +/-
fun isNumeric(str: String): Boolean = str
.removePrefix("-")
.removePrefix("+")
.all { it in '0'..'9' }
The performance would be similar
If you want to check if it is numeric (Int) the string and do something a simple solution could be:
if (myString.toIntOrNull() != null) {
//Write your code you want to execute if myString is (Int)
} else {
//Write your code you want to execute if myString is (not Int)
}
Sharing Regex matches solution, repost from my answer here
Best suited solution if negative and positive number which can be formatted with '-' and '.'
below method returns true if formatted string number matches the regex pattern
fun isPosOrNegNumber(s: String?) : Boolean {
val regex = """^(-)?[0-9]{0,}((\.){1}[0-9]{1,}){0,1}$""".toRegex()
return if (s.isNullOrEmpty()) false
else regex.matches(s)
}
Above sample regex is only for US number formats but if you want to use EU number formats then just replace '.' with ',' in regex pattern string
Note:. if the numbers contain commas then just replace it while sending to this method or better form a regex pattern with commas in it.
I searched for the same and I found this answer so I have made my own version from the above answer:
//function to check strin is int or bull
fun String.intOrString(): Boolean{
val v = toIntOrNull()
return when(v) {
null -> false
else -> true
}
}
val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
val secNum:Unit = listNumber1to100.forEach {it}
println(listNumber1to100.asSequence().filter { it%(listNumber1to100.forEach { it })!=0 }.toList())
I have an error in reminder sign!
This is Error: None of the following functions can be called with the arguments supplied
In your first approach, the error appears in this line:
it%(listNumber1to100.forEach { it })
A Byte, Double, Float, Int, Long or Short is prefered right after the % operator, however, forEach is a function which the return type is Unit.
In your second approach, you have the correct expression in isPrime(Int). Here are some suggestions for you:
listNumber1to100 is excluding 100 in your code, if you want to include 100 in listNumber1to100, the lambda you pass to takeWhile should be changed like this:
val listNumber1to100 = listNumbers.takeWhile { it <= 100 }
listNumber1to100.asSequence() is redundant here since listNumber1too100 is itself a TakeWhileSequence which implements Sequence.
isPrime(Int) is a bit confusing since it is check for isComposite and it does not work for every input it takes(it works for 1 to 99 only). I will rewrite it in this way:
fun isPrime(num: Int): Boolean = if (num <= 1) false else !(2..num/2).any { num % it == 0 }
Since prime number must be positive and 1 is a special case(neither a prime nor composite number), it just return false if the input is smaller or equal to 1. If not, it checks if the input is divisible by a range of number from 2 to (input/2). The range ends before (input/2) is because if it is true for num % (num/2) == 0, it is also true for num % 2 == 0, vise versa. Finally, I add a ! operator before that because a prime number should not be divisible by any of those numbers.
Finally, you can filter a list by isPrime(Int) like this:
println(listNumber1to100.filter(::isPrime).toList())
PS. It is just for reference and there must be a better implementation than this.
To answer your question about it, it represents the only lambda parameter inside a lambda expression. It is always used for function literal which has only one parameter.
The error is because the expression: listNumber1to100.forEach { it } - is not a number, it is a Unit (ref).
The compiler try to match the modulo operator to the given function signatures, e.g.: mod(Byte) / mod(Int) / mod(Long) - etc.
val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
fun isPrime(num: Int): Boolean = listNumber1to100.asSequence().any { num%it==0 && it!=num && it!=1 }
println(listNumber1to100.asSequence().filter { !isPrime(it)}.toList())
I found this solution and worked
But why can I have a non-number here in the right side of reminder