how to mitigate overflow in Kotlin - kotlin

Like to title suggest, I was writing operation functions in Kotlin when I encountered overflows.
Here is an Example:
fun main(args: Array<String>) {
val x: Double = 2.2
val y: Double = 1.0
val z = x - y
println("$x - $y is $z")
}
the output will be
2.2 - 1.0 is 1.2000000000000002
instead of
2.2 - 1.0 is 1.2
The functions I'm writing require double datatype variables but I keep encountering these overflows. How do I mitigate this issue?

You can use DecimalFormat
import java.text.DecimalFormat
fun main(args: Array<String>) {
val x: Double = 2.2
val y: Double = 1.0
val df = DecimalFormat("#.#")
val z = df.format((x - y)).toDouble()
println("$x - $y is $z")
}

Related

Kotlin Sorting a list of objects based on their coordinate( lat and long) using Haversine formula

I want to sort a list based on their latitude and longitude...
Here is my code:
import java.util.*
import com.google.gson.GsonBuilder
import java.io.File
import java.io.InputStream
import java.util.Comparator
data class Property(val Pcode: Int, val Locality: String, val State: String, val Comments: String, val Category: String, val Longitude: Double, val Latitude: Double)
class SortPlaces(currentLatitude: Double, currentLongitude: Double) : Comparator<Property> {
var currentLat: Double
var currentLng: Double
override fun compare(property1: Property, property2: Property): Int {
val lat1: Double = property1.Latitude
val lon1: Double = property1.Longitude
val lat2: Double = property2.Latitude
val lon2: Double = property2.Longitude
val distanceToPlace1 = distance(currentLat, currentLng, lat1, lon1)
val distanceToPlace2 = distance(currentLat, currentLng, lat2, lon2)
return (distanceToPlace1 - distanceToPlace2).toInt()
}
fun distance(fromLat: Double, fromLon: Double, toLat: Double, toLon: Double): Double {
val radius = 6378137.0 // approximate Earth radius, *in meters*
val deltaLat = toLat - fromLat
val deltaLon = toLon - fromLon
val angle = 2 * Math.asin(
Math.sqrt(
Math.pow(Math.sin(deltaLat / 2), 2.0) +
Math.cos(fromLat) * Math.cos(toLat) *
Math.pow(Math.sin(deltaLon / 2), 2.0)
)
)
return radius * angle
}
init {
currentLat = currentLatitude
currentLng = currentLongitude
}
}
fun main(args: Array<String>) {
val command = Scanner(System.`in`)
val running = true
while (running) {
val inputStream: InputStream = File("./src/main/kotlin/suburbs.json").inputStream()
val inputString = inputStream.bufferedReader().use { it.readText() }
val gson = GsonBuilder().create()
val packagesArray = gson.fromJson(inputString , Array<Property>::class.java).toList()
println("Please enter a suburb name: ")
val suburbName = command.nextLine()
println("Please enter the postcode: ")
val postcode = command.nextLine()
val userProperty: Property? = packagesArray.find{ it.Locality.toLowerCase().equals(suburbName.toLowerCase()) && it.Pcode == postcode.toInt()}
//sort the list, give the Comparator the current location
Collections.sort(packagesArray, new SortPlaces(userProperty.Latitude, userProperty.Longitude));
}
command.close()
}
I got error: Too many arguments for public open fun <T : Comparable<T!>!> sort(list: (Mutable)List<T!>!): Unit defined in java.util.Collections
at my sort{} function
my userProperty has to be Property? because the find{} method return Property?
Then Collections.sort() can not sort Property? type because the SortPLaces only accept Comparator not Comparator<Property?>
What should I do?
There are multiple errors in your code. To create a new object in Kotlin, you don't write the word new like you do in Java. Also, as you have noticed, find returns a nullable type - Property?. You need to check for nulls when using userProperty. A Property matching the criteria you want may not necessarily be found, after all.
if (userProperty != null) {
Collections.sort(packagesArray, SortPlaces(userProperty.Latitude, userProperty.Longitude))
} else {
// no property is found! Think about what you should do in such a case
}
Since you are sorting the list in line, you should not make an immutable list with toList when you are deserialising the JSON, but rather a MutableList:
val packagesArray = gson.fromJson(inputString, Array<Property>::class.java).toMutableList()
Also, you seem to be using a lot of Java APIs. In Kotlin, a lot of the Java APIs that you are using have more idiomatic Kotlin counterparts. To sort the list, you don't need the SortPlaces class at all. Simply use sortBy on the array, and call your distance function in the lambda.
data class Property(
val pcode: Int,
val locality: String,
val state: String,
val comments: String,
val category: String,
val longitude: Double,
val latitude: Double,
)
fun distance(fromLat: Double, fromLon: Double, toLat: Double, toLon: Double): Double {
val radius = 6378137.0 // approximate Earth radius, *in meters*
val deltaLat = toLat - fromLat
val deltaLon = toLon - fromLon
val angle = 2 * asin(
sqrt(
sin(deltaLat / 2).pow(2.0) +
cos(fromLat) * cos(toLat) *
sin(deltaLon / 2).pow(2.0)
)
)
return radius * angle
}
fun main(args: Array<String>) {
val running = true
while (running) {
val inputStream = File("./src/main/kotlin/suburbs.json").inputStream()
val inputString = inputStream.bufferedReader().use { it.readText() }
val gson = GsonBuilder().create()
val packagesArray = gson.fromJson(inputString , Array<Property>::class.java).toMutableList()
println("Please enter a suburb name: ")
val suburbName = readLine()
println("Please enter the postcode: ")
val postcode = readLine()
val userProperty = packagesArray.find {
it.locality.lowercase() == suburbName?.lowercase() && it.pcode == postcode?.toInt()
}
//sort the list, give the Comparator the current location
if (userProperty != null) {
packagesArray.sortBy {
distance(userProperty.latitude, userProperty.longitude, it.latitude, it.longitude)
}
} else {
// did not find such a property!
}
}
}

How to convert mile to kilometer using kotlin

I am new to kotlin... I have no idea how to convert miles to kilometer
MainActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val name = findViewById<EditText>(R.id.text1)
val ConvertButton = findViewById<Button>(R.id.btn1)
val displayanswer = findViewById<TextView>(R.id.textView1)
}
}
I don't think that's really a kotlin topic.
It's simply a math problema but here is one way to implement it in kotlin :
Using kotlin extensions you can write a function to convert km to miles and miles to km :
fun Float.toKm() = this * 1.60934
fun Float.toMiles() = this / 1.60934
Now when you will have a float that represent a km you'll be able to invoke .toMiles() and when you'll have a float that represent a miles you'll be able to invoke .toKm().
Here is an example :
val kilometers = 10.0F
val miles = 6.0F
println("km ${kilometers} to miles = ${kilometers.toMiles()}")
println("miles ${miles} to km = ${miles.toKm()}")
If you want to read more about extensions : https://kotlinlang.org/docs/extensions.html#extension-functions
I would suggest you define value classes for your types. You can then add conversion functions and arithmetic operations as well. In this example I have defined the plus operator, but you could build on this to make this more full featured
#JvmInline
value class Kilometer(val value: Float) {
fun toMeters() = Meter(value * 1000f)
operator fun plus(other: Kilometer) = Kilometer(value + other.value)
}
#JvmInline
value class Meter(val value: Float) {
fun toKilometers() = Kilometer(value / 1000f)
fun toMiles() = Mile(value / 1.604f)
}
#JvmInline
value class Mile(val value: Float) {
fun toMeters() = Meter(value * 1.604f)
}
fun useIt() {
val km1 = Kilometer(12f)
val km2 = Kilometer(20f)
val km = km1 + km2
val meters = km.toMeters()
val miles = meters.toMiles()
}

Common methods and operators for inline classes used as units of measurement in Kotlin

I am playing with the idea of using Kotlin's inline classes to express type-safe operations with units of measurement. For example, let's define units for distance, time and speed:
inline class Meters(val v: Float) {
operator fun plus(other: Meters) = Meters(v + other.v)
operator fun times(amount: Float) = Meters(v * amount)
operator fun compareTo(other: Meters) = v.compareTo(other.v)
operator fun div(other: Meters): Float = v / other.v
fun calcSpeed(time: Seconds) = MetersPerSecond(v * time.v)
// operator fun times(time: Seconds) = MetersPerSecond(v / time.v) // clash (for now?)
}
inline class Seconds(val v: Float) {
operator fun plus(other: Seconds) = Seconds(v + other.v)
operator fun times(amount: Float) = Seconds(v * amount)
operator fun compareTo(other: Seconds) = v.compareTo(other.v)
operator fun div(other: Seconds): Float = v / other.v
fun calcSpeed(distance: Meters) = MetersPerSecond(distance.v / v)
}
inline class MetersPerSecond(val v: Float) {
operator fun plus(other: MetersPerSecond) = MetersPerSecond(v + other.v)
operator fun times(amount: Float) = MetersPerSecond(v * amount)
operator fun compareTo(other: MetersPerSecond) = v.compareTo(other.v)
fun calcDistance(time: Seconds) = Meters(v * time.v)
fun calcTime(distance: Meters) = Seconds(distance.v / v)
}
The idea here is to define methods for operations that either:
Leave the unit unchanged (eg: sum, multiplication for a pure
value)
Result in a pure value (eg: division by value of the same
unit)
Result in a value of another defined unit (eg: time * distance = speed)
So that one can write expressions like:
val distance = Meters(1f)
val time = Seconds(1f)
val speed: MetersPerSecond = (distance * 0.5f).calcSpeed(time)
Looking at the operators in the example which fall into cases 1 and 2, I can clearly see a pattern, and I am wondering whether there is a way to define those methods once in a more generic fashion for all types that need this "unit-of-measurement" behavior.
I thought about having a common interface and defining operators as extension functions with generics:
interface UnitOfMeasurement { val v: Float }
operator fun <T: UnitOfMeasurement> T.plus(other: T) = T(v + other.v)
But of course this won't work because I can't instantiate a generic like that. Is there any way to achieve this?
You could make use of a factory function of measurement units, that is reified on type T. Then you use it in your operators:
interface UnitOfMeasurement { val v: Float }
inline class Meter(override val v: Float) : UnitOfMeasurement
inline class Second(override val v: Float) : UnitOfMeasurement
inline fun <reified T : UnitOfMeasurement> create(v: Float): T {
return when (T::class) {
Meter::class -> Meter(v) as T
Second::class -> Second(v) as T
else -> throw IllegalArgumentException("don't know how to create ${T::class}")
}
}
inline operator fun <reified T : UnitOfMeasurement> T.plus(other: T) = create<T>(v + other.v)
fun main() {
val a = Meter(10f)
val b = Meter(5f)
println(a + b)
val c = Second(60f)
val d = Second(30f)
println(c + d)
// println(a + c) // throws IllegalArgumentException
}
Can be tried here

Elementary functions in kotlin

Looking for a way to get elementary functions and their derivatives I approach it like this:
abstract class Fun() {
/**
* i = 0 -- the function itself,
* i = 1, 2, 3, ... -- its successive derivatives
*/
abstract fun d(i: Int, x: Float): Float
}
class Lin(val k: Float) : Fun() {
// y = k*x
override fun d(i: Int, x: Float, p: Float) = when (i) {
0 -> k * x
1 -> k
else -> 0.0f
}
}
class Sum(val fun0: Fun, val fun1: Fun) : Fun() {
// y = fun0(x) + fun1(x)
override fun d(i: Int, x: Float, p: Float) = fun0.d(i, x) + fun1.d(i, x)
}
class Example(val fun1: Fun, val fun2: Fun){
var res = fun1.d(0, 5.25f) // fun1 value at 5.25f
res = fun1.d(1, 3.29f) // fun1 first derivative at 3.29f
val sum = Sum(fun1, fun2) // sum of f1 and f2
res = sum(0, 3.78f) // sum value at 3.78f
res = sum(1, 5.69f) // sum first derivative at 5.69f
}
Is there a more idiomatic way to do it in Kotlin?
I have exposed the problem as I had done in Java, that is, classes that contain functions. My question is if I can do the same with functions, pass them on to a class like:
class ParametricCurveXYZ(val fun_x: Fun, val fun_y: Fun, val fun_z: Fun) {
fun pointToXYZ(s: Float) = VectorXYZ(fun_x.d(0, s), fun_y.d(0, s), fun_z.d(0, s))
fun tangent(s: Float) = VectorXYZ(fun_x.d(1, s), fun_y.d(1, s), fun_z.d(1, s)).normalized()
}
You can use lambdas instead of regular classes and overload operators to combine lambdas.
fun lin(k: Float) = { i: Int, x: Float ->
when (i) {
0 -> k * x
1 -> k
else -> 0.0f
}
}
operator fun ((Int, Float) -> Float).plus(that: (Int, Float) -> Float) =
{ i: Int, x: Float -> this(i, x) + that(i, x) }
fun doSomething() {
val sum = lin(1f) + lin(2f)
val res = sum(0, 3.78f)
}

Kotlin JS - string to number conversion?

How to do String to number conversion in Kotlin JS app. I am Using the following code and having some trouble converting from the HTMLInputElement value to double.
fun c2f(self: Any) {
console.log("Self object: ${self} ")
val celsius = document.getElementById("celcius")?.getAttribute("value") as Double
val fahrenheit = celsius * 1.8 + 32
console.log("Fahrenheit value: ${fahrenheit} ")
window.alert("Celcius (${celsius}) -> Fahrenheit (${fahrenheit}) ")
}
Also i am not seeing any toDouble() function on String class as in the case of JVM app.
Answering my own question as this would be helpful for somebody.
You can use the kotlin.js top level parse functions for string <-> Number conversion.
fun parseInt(s: String, radix: Int = 10): Int
fun safeParseInt(s : String) : Int?
fun safeParseDouble(s : String) : Double?
Simply use the String.toXXX() functions, e.g.
val n = "1"
val m = 2 + n.toInt()
val x = "1.1"
val y = 2.0 + x.toFloat()
etc.