Search code examples
android-jetpack-composeunit-conversion

Getting Wrong Result for the input above 4 digit


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.

enter image description here 4 digits entered

enter image description here 5 digits


Solution

  • Your code

    val value = ((convertedValue?.times(100000.0))?.roundToInt() // ...
    

    if 4 digits:

    • convertedValue = 9999
    • value = 999,900,000

    if 5 digits:

    • convertedValue = 99999
    • value = 9,999,900,000

    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