I am facing an issue where I need to do some calculations with a number like for example 5000,00 multiplied it by (1,025^3).
So in this case 5000,00 * (1,025^3) = 5385,45
So my question is, how can I format the number 5385,45 to be like 5.385,45 using decimal format maybe?
I tried by myself and I did this piece of code that outputs 5385,45 in the app but not 5.385,45
var interestValue = (5000,00*(Math.pow(1.025,yearValue)))
val number = java.lang.Double.valueOf(interestValue)
val dec = DecimalFormat("#,00")
val credits = dec.format(number)
vValueInterest.text = credits
This is the format you need:
val dec = DecimalFormat("#,###.##")
will print:
5.384,45
if you need always exactly 2 digits after the decimal point:
val dec = DecimalFormat("#,###.00")
val num = 1.34567
val df = DecimalFormat("#.##")
df.roundingMode = RoundingMode.CEILING
println(df.format(num))
When you run the program, the output will be:
1.34
Check:
https://www.programiz.com/kotlin-programming/examples/round-number-decimal
The "most Kotlin-esque" way I found to do this sort of formatting is:
"%,.2f".format(Locale.GERMAN, 1234.5678) // => "1.234,57"
"%,.2f".format(Locale.ENGLISH, 1234.5678) // => "1,234.57"
"%,.2f".format(1234.5678) // => "1,234.57" for me, in en_AU
Note though that even though this is Kotlin's own extension method on String, it still only works on the JVM.
For those looking for a multiplatform implementation (as I was), mp_stools is one option.
Used:
%.numberf
fun main(args: Array<String>) {
var A: Double
A = readLine()!!.toDouble()
var bla = A*A
var calculator = 3.14159 * bla
println("A=%.4f".format(calculator))
}
Try val dec = DecimalFormat("#.###,00"). For examples of DecimalFormat check this link.
Related
I have a firebase realtime database
with this simple scheme:
admin
price1: 5
if i get database in kotlin:
val result = it.value as MutableMap<String, Any>
When i try to get price1
var price1 = result["price1"] as Long
price1 = price1 + 1
(PRICE1 can be Double or Int)
the problem is that if price 1 is 5.5 obviously app killed, but if price 1 is 5, works perfectly.
In swift, i put Double every time and it never gives problems
I find it a bit silly to have to check if it is a double or an int without a comma to be able to do the sum
// im doing this at the moment
var price1 = result["price1"].toString()
if (price1.contains(".")){
println(price1.toDouble() + 1)
}else{
println(price1.toInt() + 1)
}
Exist other simple way?
Thanks everyone
Kotlin is very strict about types, which is important for type safety.
In your case, you get a value of type Any out of result. It could be anything, not only an Int or a Double. You know that it can only be an Int or a Double, but the compiler doesn't. Many languages allow implicit stuff like type conversion (int to double), type widening (int to long), etc. But these are often sources of nasty errors. See also this discussion Does anybody find Kotlin’s Type Casting disgusting?
Regarding your code: To test a value for its type you use is.
Here is an example of how you could increment by one:
fun increment(value: Any): Any {
return when (value) {
is Double -> value + 1.0
is Int -> value + 1
else -> throw Exception("Value is neither a Double nor an Int")
}
}
And you would use it like this:
val result: MutableMap<String, Any> = mutableMapOf(
"price1" to 3,
"price2" to 3.45
)
var price1: Any = result["price1"]!! // 3
price1 = increment(price1)
println(price1) // 4
price1 = increment(price1)
println(price1) // 5
var price2: Any = result["price2"]!! // 3.45
price2 = increment(price2)
println(price2) // 4.45
price2 = increment(price2)
println(price2) // 5.45
I don't know if Kotlin will ever have union types. Then a declaration like this would be possible:
val result: MutableMap<String, [Int|Double]> // invalid code
In kotlin all numerable types like Long, Int, Double etc inherit abstract class Number
So your map declaration could be Map<String, Number>.
The Number may be easily converted to Double or any other numerable type and then you can work with it as you do in swift:
val map = hashMapOf<String, Number>(
"1" to 5.5,
"2" to 5
)
var value1 = requireNotNull(map["1"]).toDouble()
val value2 = requireNotNull(map["2"]).toDouble()
value1++
PS: never use serialization to string as a way to check a type, you can use is operator as #lukas.j suggested
I'm trying to self-teach Kotlin with the Google Android Dev Courses (I started a week ago and have very little experience in coding).
At the end of the course that thaught me to build a working Tip Calculator, there was an optional exercise to create a similar app.
I chose to create an Animal Age Calculator but i can't manage to bind the result to its TextView.
The output that i get is Animal age: %s .
The ouput that i want is the result of either my catAgeFormula(age) or my dogAgeFormula(age)
I understand it's showing me this : <string name="animal_age">Animal age: %s</string>
But the thing i don't understand is why my binding doesn't work binding.ageResult.text = getString(R.string.animal_age)
Here is the complete function i'm not sure about :
private fun calculateAge() {
val stringInTextField = binding.userAge.text.toString()
val age = stringInTextField.toIntOrNull()
if (age == null || age == 0) {
binding.ageResult.text = "0"
return
}
when (binding.animalOptions.checkedRadioButtonId) {
R.id.option_cat -> catAgeFormula(age)
else -> dogAgeFormula(age)
}
binding.ageResult.text = getString(R.string.animal_age)
}
And the output TextView :
<TextView
android:id="#+id/age_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/calculate_button"
tools:text="Animal age : 42 years" />
This is my first post on Stack Overflow so i'm really sorry if messed up something.
Thanks in advance for you help :)
You are missing an argument on the getString method
private fun calculateAge() {
val stringInTextField = binding.userAge.text.toString()
//...
binding.ageResult.text = getString(R.string.animal_age, stringInTextField)
}
Your string is:
<string name="animal_age">Animal age: %s</string>
The %s means it expects to receive 1 String type argument. The method getString can receive 2 arguments. The first is the id of the resource string and the second a vararg that can be any number of other arguments. This is because a string defined on the resources can take up any number of other arguments, by example:
<string name="example">Example %1$s %2$d</string>
Where %2$d it would be a number expected as a second argument
val example = getString(R.string.example, "one", 2)
//Example one 2
You can refer to the official documentation for further explanations
Thanks to cutiko, i found out i was missing a variable for the code to work properly.
I added my when statement into a variable named animalAge and used it as a second argument to my getString method.
Here is the final working function :
private fun calculateAge() {
val stringInTextField = binding.userAge.text.toString()
val age = stringInTextField.toIntOrNull()
//...
val animalAge = when (binding.animalOptions.checkedRadioButtonId) {
R.id.option_cat -> catAgeFormula(age)
else -> dogAgeFormula(age)
}
binding.ageResult.text = getString(R.string.animal_age, animalAge)
}
And the final working string resource :
<string name="animal_age">Animal age: %d</string>
The default of Double in android kotlin is 1121.57. How to convert it to 1.121,5767 to make 4 number after comma? even though behind the comma is 0 like this: 1.121,0000
You could write an extension function for Double and use a German format for the output, like this:
fun main() {
val myDouble: Double = 1121.57
val anotherDouble: Double = 100000.99
println(myDouble.format(4))
println(anotherDouble.format(4))
}
fun Double.format(digits:Int) = String.Companion.format(
java.util.Locale.GERMAN,
"%#,.${digits}f",
this
)
It returns the following String
1.121,5700
100.000,9900
please pass your value to the following function and let me know if it works for you.
fun formattedNumber(number: Double): String{
val formattedNumber = String.format("%.7f", number)
val split = formattedNumber.split(".");
val str = StringBuilder(split[1])
str.insert(3, ',')
return "${split[0]}.${str}"
}
Take a look at the BigDecimal class. You can easily set the scale to 4 digits and it can be created with a Double.
Can anybody explain how I can release an app-level kotlin function in Android Studio project? I have an Android application and I try do someting like this:
var date: Date = Date()
/////////////////////////////////////////////////////////
// this block must be app-level fun
val format = “dd.MM.yyyy”
val simpleDateFormat = SimpleDateFormat(format)
var formattedDate = simpleDateFormat.format(date)
/////////////////////////////////////////////////////////
convert Date object to String with custom format. I do it many times (in different activities and fragments) in my project, so I think it will be good idea to releas this code as function (or class, if it will be more efficient). Thus I have date and format as input parameters and formattedDate as output. Also it will be good to set default format value
You can create an extension function on Date that accepts a format and uses it to convert the date to that format. You can also define the default format on the input parameter. Something like:
fun Date.toFormattedString(format: String = "dd.MM.yyyy"): String {
val simpleDateFormat = SimpleDateFormat(format)
return simpleDateFormat.format(this)
}
Place it in a file where the whole app can access it (e.g., a file named Extensions.kt in a module/package where you put all reusable and/or helper code) and then just use the function like someDate.toFormattedString().
Here is an example of my function contained in separate kotlin file called Time.kt
fun timeConverter(string: String?, i: Int): String {
val isoFormat = "yyyy-MM-dd'T'HH:mm:ss"
var expectedFormat = "dd/MM"
when(i){
0 -> expectedFormat = "dd/MM"
1 -> expectedFormat = "EEE"
2 -> expectedFormat = "HH:mm"
3 -> expectedFormat = "EEE, dd/MM"
}
val dateFormat = SimpleDateFormat(isoFormat, Locale.getDefault())
val date = dateFormat.parse(string)
return SimpleDateFormat(expectedFormat).format(date)
}
Make the function part of an object.
https://www.baeldung.com/kotlin-objects
Objects (not class) in Kotlin are static. If you import the object from where you use the function, it can be used anywhere without being instantiated.
You can have a DateUtil class that holds a format function as companion. You will be able to use it anywhere in your app without instantiating it.
class DateUtil{
companion object {
fun format(date: Date):String{
val format = "dd.MM.yyyy"
val simpleDateFormat = SimpleDateFormat(format)
return simpleDateFormat.format(date)
}
}
}
Then you call it: DateUtil.format(Date())
In our project I want to pass string with dollar sign. Final result should look like this: ~ $1300. But I get only ~ the rest is not print. By debugging I found out that the issue is the dollar sign. How I can pass strings with dollar sign? Escaping dollar sign not solving this problem.
fun setItem() {
bind(valueSubtitle = "~ \$${trx.currencyAmount}")
}
fun bind(valueSubtitle: String? = null) {
val valueSubtitleTextView = findViewById(R.id.txtValueSubtitle)
valueSubtitleTextView.text = valueSubtitle
}
I don't have issues with direct printing string with dollar sign. I have issue when I try to pass this string to other function, and only then print it.
Update
I debugged, and found out that I have issue when my number has double zero at the end: 189.00 or 123.00. These number causes the problem. Other number like 123.40 or 1152.90 shows correctly.
Update 2
Issue was with my TextView. It behaved strangely when it was printing different double numbers. It was solved when I changed android:layout_width="match_parent" to android:layout_width="wrap_content"
You could try for a literal representation.
fun main(args: Array<String>) {
val amount = "25"
val escapedString = "~ ${'$'}$amount"
printString(escapedString)
}
fun printString( str : String) {
println(str)
}
Templates are supported both inside raw strings and inside escaped strings. If you need to represent a literal $ character in a raw string (which doesn't support backslash escaping), you can use the following syntax:
itemAmount.bind(valueSubtitle = "~ \${'$'}${trx.currencyAmount}")
Looks pretty bad syntax, but will work.
Try this
class MainActivity : AppCompatActivity() {
private val trx: Transaction = Transaction(1300.00)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setItem()
}
fun setItem() {
bind(valueSubtitle = "~ \$${trx.currencyAmount}")
}
fun bind(valueSubtitle: String? = null) {
val valueSubtitleTextView: TextView = findViewById(R.id.textview)
valueSubtitleTextView.text = valueSubtitle
}
class Transaction(var currencyAmount: Double)
}
There is nothing wrong with the code you have shown. Note also that you can use several ways to escape the dollar sign and that in your specific case you wouldn't even need to escape it. Just compare with the following sample code:
data class Container(val amount : Double = 123.00)
fun main() { // used Kotlin 1.3
val trx = Container()
listOf("~ \$${trx.amount}", // your variant
"~ $${trx.amount}", // easier and works too
"""~ $${trx.amount}""", // everything in this string must not be escaped
"~ ${'$'}${trx.amount}", // actually you may only use this if you require something like shown below (e.g. if you want to print something like $none)
"""~ ${"$"}${trx.amount}""", // similar to the one before
// variants to print $none:
"~ \$none",
"~ ${'$'}none",
"""~ ${'$'}none""",
"""~ $${""}none"""
)
.forEach(::println)
}
The output of the above is:
~ $123.0
~ $123.0
~ $123.0
~ $123.0
~ $123.0
~ $none
~ $none
~ $none
~ $none
But none of these answers were the solution to your problem. As the $ in your code wasn't the problem as you found out yourself...
This should work.
fun main(args: Array<String>) {
val dollar = "~$"
val amount = 1212
println("${dollar}${amount}")
}