I have encountered a problem when handling floats in an Android application
My case regards handling decimal places in kotlin Float
, but I think it can be applied to Java.
Let's assume that I have an EditText
which is a Number
field in an Android app. This way, an user can just input an integer, and by an integer I mean a whole number, not the primitive data type. It's then passed to the code as a String
so it doesn't matter.
private lateinit var weightText: EditText
private lateinit var heightText: EditText
Let's say that the user inputs two numbers - 120 and 174.
weightText = findViewById(R.id.etWeight)
heightText = findViewById(R.id.etHeight)
Then I am making an Body Mass Index calculation on them:
val bmiEquals = weight.toFloat() / ((height.toFloat() / 100) * (height.toFloat() / 100))
Easy.
But bmiEquals
in this case is equal to 38.73967
Now I'd like to display the user this number with just two decimal places: 38.74
To achieve this I do:
val df = DecimalFormat("#.##")
val bmi2Digits = df.format(bmiEquals)
It was working fine in the Android emulator, but when I've tested the code on my physical device, I've encountered a problem here:
private fun displayResult(bmi: String) {
when (bmi.toFloat()) {
I got an error cause bmi
variable was not 38.74
but 38,74
. I have researched a bit and it seems that this is caused by locale. In some countries, you divide floating point numbers using a dot, in some others - a comma. And DecimalFormat is used to format a number to a String
.
I know that I could just use BigDecimals here, but I wonder if there is any way to handle this case while working on Floats
.
Honestly? I have solved this problem using a silly solution:
when (bmi.replace(',', '.').toFloat()) {
But it is bothering me so hard... ;)
CodePudding user response:
you may always check which character is an decimal separator on running device using
DecimalFormatSymbols.getInstance().getDecimalSeparator()
CodePudding user response:
try following round functionality from import kotlin.math.round
var bmi2Decimal = round(bmiEquals * 100)/100
bmi2Decimal is float and in this case, 100 is used to make it 2 decimal place
CodePudding user response:
You may use DecimalFormat with a specific locale.
val bmiEquals = 38.73967
Locale.setDefault(Locale.FRENCH)
val dfUS = DecimalFormat("#.##", DecimalFormatSymbols(Locale.US))
// or df.decimalFormatSymbols = DecimalFormatSymbols(Locale.US)
val dfResultUS = dfUS.format(bmiEquals)
println(dfResultUS) // output: 38.74
val dfLocale = DecimalFormat("#.##")
val dfResultLocale = dfLocale.format(bmiEquals)
println(dfResultLocale) // output: 38.74