Drop un-needed decimal ".0" - android

I'm making a simple calculator and I am having an issue with it showing a decimal on what I want to just be a whole number. For example, if the entered expression is "50 + 50" the answer will come out "100.0". I understand that it's happening because my output is set as a double, but I can't figure out how to convert those numbers to integer only when the answer is ".0".
My output answer code:
fun equal (view: View) {
secondnum = editText.text.toString()
decpressed = 0
var sum = 0.0
when (op) {
"+" -> {sum = (firstnum.toDouble() + secondnum.toDouble())}
"-" -> {sum = (firstnum.toDouble() - secondnum.toDouble())}
"*" -> {sum = (firstnum.toDouble() * secondnum.toDouble())}
"/" -> {sum = (firstnum.toDouble() / secondnum.toDouble())}
}
editText.setText(sum.toString())
textView.text = "$firstnum $op $secondnum ="
zero = true
}

You can use removeSuffix:
fun main() {
println(100.5.toString().removeSuffix(".0"))
println(100.0.toString().removeSuffix(".0"))
}
Output:
100.5
100

Related

How do I go about and Find Min Max Values in a Kotlin App

I made a stat calculator and I need to store 10 user inputted values to be stored in an array where I can get the average and lowest number. How do I go about getting the values on the array to get the maximum and minimum values?
var values = ArrayList<Int>()
var count = 0
var arrCount = 0
addButt.setOnClickListener {
values.add(statNum.text.toString().toInt())
count++
arrCount++
var i = 0
statNum.setText("")
statArray.text = ""
for (i in 0..arrCount - 1) {
statArray.text = statArray.text as String + values[i] + ","
}
}
avgBut.setOnClickListener{
val statArray = doubleArrayOf(4.0, 7.0, 11.0, 12.0, 9.0)
var sum = 0.0
for (num in statArray) {
sum += num
}
val average = sum / statArray.size
finalAnswer.text = average.toString()
}
minmaxBut.setOnClickListener{
fun findMin(list: List<Int?>): Int? {
return list.sortedWith(compareBy { it }).first()
}
fun findMax(list: List<Int?>): Int? {
return list.sortedWith(compareBy { it }).last()
}
fun main() {
val list = listOf(10, 4, 2, 7, 6, 9)
val min = findMin(list)
finalAnswer.text = "Min Vale = $min"
val max = findMax(list)
println(max) // 10
}
It's very easy to get min, max and average number in the arraylist. I did not understand your code clearly but i will share how you can do these. After you may use that on your array:
val list = arrayListOf<Int>(1,2,3,4,5,6,7,8,9,10)
Log.e("min", list.min().toString())
Log.e("max", list.max().toString())
Log.e("average", list.average().toString())
This will give you below output in logcat:
E/min: 1
E/max: 10
E/average: 5.5

How do you remove extra zeros at the end of a decimal in Kotlin?

I'm creating a function that rounds large numbers over 1,000 and then returns a string of that rounded number. For example, "2374293" would return as "2.37m"
However, I dont want any extra zeros at the end of decimals like "25.00" or "100.50".
For Example:
What I want:
Input -> Output
"11000" -> "11k"
"11400" -> "11.4k"
What I get:
Input -> Output
"11000" -> "11.00k"
"11400" -> "11.40k"
How would I remove these zeros and decimal point(if it's a whole number) when needed?
Here is my code currently:
private fun roundBigNumb(numb: Long): String {
val newNumb = numb.toDouble()
return when {
numb in 1000..999994 -> {
BigDecimal(newNumb/1000).setScale(2, RoundingMode.HALF_EVEN).toString()+"k"
}
numb in 999995..999999 -> {
"999.99k"
}
numb in 1000000..999994999 -> {
BigDecimal(newNumb/1000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"m"
}
numb in 999995000..999999999 -> {
"999.99m"
}
numb in 1000000000..999994999999 -> {
BigDecimal(newNumb/1000000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"b"
}
numb in 999995000000..999999999999 -> {
"999.99b"
}
numb in 1000000000000..999994999999999 -> {
BigDecimal(newNumb/1000000000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"t"
}
numb in 999995000000000..999999999999999 -> {
"999.99t"
}
numb >= 1000000000000000 -> "∞"
else -> numb.toString()
}
}
import java.math.BigDecimal
import java.math.RoundingMode.HALF_EVEN
fun roundBigNumber(number: Long): String {
fun calc(divisor: Long) = BigDecimal(number.toDouble() / divisor)
.setScale(2, HALF_EVEN)
.toString()
.dropLastWhile { it == '0' }
.dropLastWhile { it == '.' }
return when {
number in 1000..999994 -> calc(1000) + "k"
number in 999995..999999 -> "999.99k"
number in 1000000..999994999 -> calc(1000000) + "m"
number in 999995000..999999999 -> "999.99m"
number in 1000000000..999994999999 -> calc(1000000000) + "b"
number in 999995000000..999999999999 -> "999.99b"
number in 1000000000000..999994999999999 -> calc(1000000000000) + "t"
number in 999995000000000..999999999999999 -> "999.99t"
number >= 1000000000000000 -> "∞"
else -> number.toString()
}
}
Once you have converted the number to a string with up to 2 decimal places (as you are doing), you can use dropLastWhile to drop trailing zeros and decimal places.
Here is an example
fun prettyFormat(input: Double): String {
if( input == 0.0 ) return "0"
val prefix = if( input < 0 ) "-" else ""
val num = abs(input)
// figure out what group of suffixes we are in and scale the number
val pow = floor(log10(num)/3).roundToInt()
val base = num / 10.0.pow(pow * 3)
// Using consistent rounding behavior, always rounding down since you want
// 999999999 to show as 999.99M and not 1B
val roundedDown = floor(base*100)/100.0
// Convert the number to a string with up to 2 decimal places
var baseStr = BigDecimal(roundedDown).setScale(2, RoundingMode.HALF_EVEN).toString()
// Drop trailing zeros, then drop any trailing '.' if present
baseStr = baseStr.dropLastWhile { it == '0' }.dropLastWhile { it == '.' }
val suffixes = listOf("","k","M","B","T")
return when {
pow < suffixes.size -> "$prefix$baseStr${suffixes[pow]}"
else -> "${prefix}infty"
}
}
This produces
11411.0 = 11.41k
11000.0 = 11k
9.99996E8 = 999.99M
12.4 = 12.4
0.0 = 0
-11400.0 = -11.4k
If you don't care about zero or negative numbers it can be simplified a bit.

Calculator rounding to fit in editText

I have an editText limited to 14 characters. This works to limit the number the user inputs but it just cuts off numbers bigger than 14 characters(even after the decimal) in the answer. So, two problems I need help with. How do I make it so that errors if the value is larger than 14 digits, and to always round to the best place(like if the sum is 164541254.4568727(17char), it will round to 164541254.4569(14char) or 12.9876543210987 rounds to 12.9876543211)
Equal button code(because I think this is where I'll need to put the code):
fun equal(view: View) {
secondnum = editText.text.toString()
decpressed = 0
var sum = 0.0
when (op) {
"+" -> {
sum = (firstnum.toDouble() + secondnum.toDouble())
}
"-" -> {
sum = (firstnum.toDouble() - secondnum.toDouble())
}
"*" -> {
sum = (firstnum.toDouble() * secondnum.toDouble())
}
"/" -> {
if (secondnum == "0") {
Toast.makeText(this, "Can not divide by 0!", Toast.LENGTH_LONG).show()
editText.setText("0")
textView.text = ""
} else {
sum = (firstnum.toDouble() / secondnum.toDouble())
}
}
}
val out = DecimalFormat("#.##########")
out.roundingMode = RoundingMode.HALF_EVEN
editText.setText(out.format(sum))
textView.text = "$firstnum $op $secondnum ="
zero = true
}
If other code is needed, please request it.

How to replace NaN value with 0, = Zero, != null in Kotlin for speed?

When i start my app, which should get the speed of the device, i get a NaN( i think its for " not a number"?) value for 1- 3 seconds in the textfield.The numbers are safed in a repository, but if is Nan, the app crashes.
How can i replace this NaN with 0(Zero)?... for ex.: If( NaNvalue = true){ (value = 0)}...something like that. I didnt find anything written in android or kotlin, just python(which i am not familiar with).
Any help would be great!!! Thank you...
my code:
fun getSpeed(location: Location): Float{
if (mRunning ) {
// val getkmh = (location.speed * 3.6)
// mSpeedKmH = getkmh.toFloat()
mElapsedSeconds = ((SystemClock.elapsedRealtime()
-mChrono!!.getBase()) / 1000)
mSpeedMeter = mDistanceTotal/mElapsedSeconds.toFloat()
mSpeed = ( mSpeedMeter *3.6).toFloat()// *3.6 > KmH
}
return mSpeedKmH
}
fun updateSpeed() {
val speedMeter = String.format(Locale.getDefault(), "%.1f",mSpeed)
tvSpeed.text = speedMeter
}
You can do it like the other answer shows or using takeIf and the elvis operator:
val speedMeter = String.format(Locale.getDefault(), "%.1f", mSpeed.takeIf { !it.isNaN() } ?: 0.0)
val value: Double = yourDoubleValue.let { if (it.isNaN()) 0.0 else it}
The same can be applied to Float values
Thanks to Fernando and Tenfour04!!! Both versions are working!!
val speedGesammt = String.format(Locale.getDefault(), "%.1f",
mSpeedAverageKmH.takeIf { !it.isNaN() } ?: 0.0)
val speedGesammt = String.format(Locale.getDefault(), "%.1f",
mSpeedAverageKmH.let { if (it.isNaN()) 0.0 else it})

Initializing an Array using lambda with conditions in Kotlin

Info
I have an Item class file as follows:
class Item(var color:String, var numValue:Int, var drawableID:Int){
init {
color = this.color
numValue = this.numValue
drawableID = this.drawableID
}
}
In the main code I create an array which contains 104 objects by default attributes:
var myItemClassArray = Array(104) { Item("", -99, -99) }
Also I have pictures in my drawable folder and I have their IDs in an array which is drawablesIDs:Array<Int>, and it contains 53 elements.
Problem
I want to assign my Item attributes as in this picture: https://i.stack.imgur.com/wFVsn.png I can do it for a similar problem (which has 106 objects and 53 drawables) with the code given in below:
for (i in 0 until 106) {
if (i < 13) {
myItemClassList[i+2].color = "kirmizi"
myItemClassList[i+2].numValue = i+1
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 13..25) {
myItemClassList[i+2].color = "siyah"
myItemClassList[i+2].numValue = (i+1)-13
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 26..38) {
myItemClassList[i+2].color = "yesil"
myItemClassList[i+2].numValue = (i+1)-26
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 39..51) {
myItemClassList[i+2].color = "mavi"
myItemClassList[i+2].numValue = (i+1)-39
myItemClassList[i+2].drawableID = drawablesIDs[i+1]
} else if (i in 52..64) {
myItemClassList[i+2].color = "kirmizi"
myItemClassList[i+2].numValue = (i+1)-52
myItemClassList[i+2].drawableID = drawablesIDs[(i+1)-52]
} else if (i in 65..77) {
myItemClassList[i+2].color = "siyah"
myItemClassList[i+2].numValue = (i+1)-65
myItemClassList[i+2].drawableID = drawablesIDs[i+1-65+13]
} else if (i in 78..90) {
myItemClassList[i+2].color = "yesil"
myItemClassList[i+2].numValue = (i+1)-78
myItemClassList[i+2].drawableID = drawablesIDs[i+1-78+26]
} else if (i in 91..103) {
myItemClassList[i+2].color = "mavi"
myItemClassList[i+2].numValue = (i+1)-91
myItemClassList[i+2].drawableID = drawablesIDs[i+1-91+39]
} else {
myItemClassList[0].color = "sahte"
myItemClassList[0].drawableID = drawablesIDs[0]
myItemClassList[1].color = "sahte"
myItemClassList[1].drawableID = drawablesIDs[0]
}
}
Is there a cleaner way to do this?
One can use lambda expression to create an array. For example:
val test = Array(28){i-> examples[i]}
This works fine with one "i" parameter. But if I want to try something like this:
val test = Array(28){if(i<13)-> examples[i]}
it gives me an error because of it's syntax is wrong.
More Simple Question
Let's say we have an array which has numbers from 0 to 28 like this:
val testNumbers= Array(28){i->i}
Now I want to create an array which will contain numbers from 0 to 10 using lambda.
How do I this:
val player6 = Array(10){(it<10) -> testNumbers[it]} // gives an syntax error
From what I could gather from your picture, I've made these three assumptions:
The numValue is grouped in groups of 13 items
Each group receives a color in the order: kirmizi -> siyah -> yesil -> mavi, then it cycles again
The drawable IDs cycles every 52 items
Based on this, I came up with the following solution:
data class Item(var color: String = "", var numValue: Int = -99, var drawableId: Int = -99)
fun main() {
val colors = listOf("kirmizi", "siyah", "yesil", "mavi")
val drawableIDs = (0..52).toList() // This is just a stub. in your case it will be your drawable lists
val edgeCase = arrayListOf(Item("sahte", drawableId = drawableIDs[0]), Item("sahte", drawableId = drawableIDs[0]))
val pattern = (0 until 104)
.map { index -> Pair(index, index / 13) }
.map { (index, group) ->
Item(
color = colors[group % 4],
numValue = index+1,
drawableId = drawableIDs[(index % 52) + 1]
)
}
val total = pattern + edgeCase
total.forEach { println(it) }
}
You can play around with it on this kotlin playground.
Is there a cleaner way to do this?
From what I gather, you want to initialize only the first 13 values of a contiguous array with 28 spaces, leaving the rest with either their default values or null.
The reason why your code doesn't work is because the Array initializer expects you to return an object. the if block by itself is not an expression in kotlin, so it doesn't evaluate to a value, so you need to provide an else branch for it to work.
val examples = Array(28) { if (i < 13) examples[i] else defaultExample }
This is stated in the Kotlin documentation for control flow:
If you're using if as an expression rather than a statement (for example, returning its value or assigning it to a variable), the expression is required to have an else branch.
More simple question
In this case you could just use take:
// If you don't want to modify it
val player6 = testNumbers.take(10)
.toTypedArray() // Since take returns a List, you need to turn it back into an array
// If you want to modify the items
val player6 = testNumbers.take(10)
.map { value -> modifyNumber(value) }
.toTypedArray()
Tip: In kotlin if you declare your constructor parameter with val or var they are already attributes from your class and you don't need to initialize manually in the init block.
/*
* You don't need to do this:
* class Item(var color: String, var numValue: Int, var drawableId: Int) {
* init {
* this.color = color
* this.numValue = numValue
* this.drawableId = drawableId
* }
* }
*/
// Kotlin already does it for you
class Item(var color: String, var numValue: Int, var drawableId: Int)
fun main() {
val myitem = Item("blue", 20, 100)
println(myitem.color)
println(myitem.numValue)
println(myitem.drawableId)
}
Here is a possible solution :
fun getColor(i: Int) = when (i) {
in 0..1 -> "sahte"
in 2..13, in 52..64 -> "kirmizi"
in 65..77, in 13..25 -> "siyah"
in 26..38, in 78..90 -> "yesil"
in 39..51, in 91..103 -> "mavi"
else -> ""
}
fun getNumValue(i: Int) = when (i) {
in 0..1 -> -99
in 2..13 -> i - 1
in 13..25 -> (i - 1) - 13
in 26..38 -> (i - 1) - 26
in 39..51 -> (i - 1) - 39
in 52..64 -> (i - 1) - 52
in 65..77 -> (i - 1) - 65
in 78..90 -> (i - 1) - 78
in 91..103 -> (i - 1) - 91
else -> -99
}
fun getDrawableID(i: Int) = when (i) {
in 0..1 -> drawablesIDs[0]
in 2..13, in 13..25, in 26..38, in 39..51 -> drawablesIDs[i - 1]
in 52..64 -> drawablesIDs[(i - 1) - 52]
in 65..77 -> drawablesIDs[i - 1 - 65 + 13]
in 78..90 -> drawablesIDs[i - 1 - 78 + 26]
in 91..103 -> drawablesIDs[i - 1 - 91 + 39]
else -> -99
}
val myItemClassArray = Array(104) {
Item(getColor(it), getNumValue(it), getDrawableID(it))
}
Maybe there is some mistakes in the different ranges.
The main advantages are :
each mapping is testable independently
no mutability

Categories

Resources