I am Creating a unit conversion app e.g.:- meter to centimeter, feet to kilometer.
This screen is for temperature unit conversion. The problem arises when I enter more than 4 digits, till 4 digits the results are accurate.
I want it to add as many digits as I can enter in the input TextField and still achieve accurate results.
~~~kotlin
@Composable
fun TemperatureScreen(
conversionModel: ConversionModel,
navController: NavHostController
) {
val focusRequester = remember { FocusRequester() }
var number by rememberSaveable { mutableStateOf("1") }
var sourceUnit by remember { mutableStateOf(TemperatureUnits.Kelvin) }
var targetUnit by remember { mutableStateOf(TemperatureUnits.DegreeCelsius) }
var expandedSU by remember { mutableStateOf(false) }
var expandedTU by remember { mutableStateOf(false) }
val convertedValue = number.toDoubleOrNull()?.let { convertTemperatureValueTo(it, sourceUnit, targetUnit) }
// Here i have limited the decimal value to 5 digits
val value = ((convertedValue?.times(100000.0))?.roundToInt()?.div(100000.0))
//here I have got rid of scientific notation eg: 1.2345678E7.
var roundedValue = value?.toBigDecimal()?.toPlainString()
fun convertTemperatureValueTo(value: Double, sourceUnit: TemperatureUnits, targetUnit: TemperatureUnits): Double {
return when (sourceUnit) {
TemperatureUnits.Kelvin -> when (targetUnit) {
TemperatureUnits.Kelvin -> value
TemperatureUnits.DegreeCelsius -> kelvinToCelsius(value)
TemperatureUnits.Fahrenheit -> kelvinToFarhenheit(value)
TemperatureUnits.Rankine -> kelvinToRankine(value)
}
TemperatureUnits.DegreeCelsius -> when (targetUnit) {
TemperatureUnits.Kelvin -> celsiusToKelvin(value)
TemperatureUnits.DegreeCelsius -> value
TemperatureUnits.Fahrenheit -> celsiusToFahrenheit(value)
TemperatureUnits.Rankine -> celsiusToRankine(value)
}
TemperatureUnits.Fahrenheit -> when (targetUnit) {
TemperatureUnits.Kelvin -> fahrenheitToKelvin(value)
TemperatureUnits.DegreeCelsius -> fahrenheitToCelsius(value)
TemperatureUnits.Fahrenheit -> value
TemperatureUnits.Rankine -> fahrenheitToRankine(value)
}
TemperatureUnits.Rankine -> when (targetUnit) {
TemperatureUnits.Kelvin -> rankineToKelvin(value)
TemperatureUnits.DegreeCelsius -> rankineToCelsius(value)
TemperatureUnits.Fahrenheit -> rankineToFahrenheit(value)
TemperatureUnits.Rankine -> value
}
}
}
//---------------------------------Kelvin To Any--------------------------------------------------------------------
fun kelvinToCelsius(kelvin: Double): Double {
return kelvin - 273.15
}
fun kelvinToFarhenheit(kelvin: Double): Double {
return (kelvin - 273.15) * 9/5 + 32
}
fun kelvinToRankine(kelvin: Double): Double {
return kelvin * 1.8
}
//---------------------------------Celsius To Any--------------------------------------------------------------------
fun celsiusToKelvin(celsius: Double): Double {
return celsius + 273.15
}
fun celsiusToFahrenheit(celsius: Double): Double {
return (celsius * 9/5) + 32
}
fun celsiusToRankine(celsius: Double): Double {
val kelvin = celsius + 273.15
return kelvin * 1.8
}
//---------------------------------fahrenheit To Any--------------------------------------------------------------------
fun fahrenheitToKelvin(fahrenheit: Double): Double {
return (fahrenheit - 32) * 5/9 + 273.15
}
fun fahrenheitToCelsius(fahrenheit: Double): Double {
return (fahrenheit - 32) * 5/9
}
fun fahrenheitToRankine(fahrenheit: Double): Double {
return fahrenheit + 459.67
}
//---------------------------------rankine To Any--------------------------------------------------------------------
fun rankineToKelvin(rankine: Double): Double {
return rankine * 5/9
}
fun rankineToCelsius(rankine: Double): Double {
return (rankine - 491.67) * 5/9
}
fun rankineToFahrenheit(rankine: Double): Double {
return rankine - 459.67
}
~~~
The code is able to generate accurate results for 4 digits entered in the text field, exceeding 4 digits gives unexpected results.
4 digits entered
5 digits
Your code
val value = ((convertedValue?.times(100000.0))?.roundToInt() // ...
if 4 digits:
if 5 digits:
Integer maximum value is 2,147,483,647
So you are getting an Integer overflow with 5 digits and value
will not be what you expect.
Avoid using roundToInt()
in sums you expect >= 10 digit answers