I need to convert double precision floating point values (Double) to string and back in a format that should be culture independent.
What is the idiomatic way of doing it Kotlin?
BR.
I need to convert double precision floating point values (Double) to string and back in a format that should be culture independent.
What is the idiomatic way of doing it Kotlin?
BR.
Share Improve this question edited Nov 20, 2024 at 9:39 DarkBee 15.5k8 gold badges72 silver badges117 bronze badges asked Nov 20, 2024 at 9:33 V.LorzV.Lorz 3952 silver badges13 bronze badges 2- What exactly do you mean with "culture independent"? Like decimal dot vs. comma, or other things? It would be helpful if you could present some examples. (Here's a similar question for currencies I remember, not sure if that helps.) – tobias_k Commented Nov 20, 2024 at 9:54
- "culture independent" is approximately equivalent to regional configuration independent. It means, amongst many other things, how numbers are represented in text form for human readability. – V.Lorz Commented Nov 20, 2024 at 10:04
3 Answers
Reset to default 2Assuming you are using Kotlin/JVM, the toString
methods are not Locale-dependent; therefore you can just use number.toString()
and string.toDouble()
. The result will be the same as the original number, even though some numbers cannot be exactly represented as decimal. This is because the toString()
function will create a string that has just enough decimal precision to uniquely identify the value's Double
representation.
Example:
val d = 0.1 + 0.2
// toString() gives 0.30000000000000004. This is correct and not Kotlin's fault.
// See https://0.30000000000000004 for explanation
val s = d.toString()
println(s)
val d2 = s.toDouble()
println(d == d2) // prints "true"
To the extent of what I could check and test, the answers provided by Klitos Kyriacou and Uddyan Semwal are both useful and correct, so this is just for sharing another finding.
Regarding the implementations of toString()
and toDouble()
, I've just learned they are based on specifications given by standards, IEEE 754 and ECMAScript, and provide consistent interoperation for JVM, Kotlin Multiplatform and Kotlin Native. So, to my opinion, this is the way to go.
Using DecimalFormat(...).format(...)
and NumberFormat.getInstance(...).parse(...)
seems to be more appropriated when it is necessary to use a specific locale or regional configuration, or when it is a requirement to make numbering formats configurable. It could do the job in my use case, but would add an overhead when compared to using the default implementations for toDouble()
and toString()
.
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.*
fun doubleToString(value: Double): String {
val format = DecimalFormat("#.####################") // Pattern with precision to your liking
format.decimalFormatSymbols = DecimalFormatSymbols(Locale.US) // Ensure culture independence (e.g., dot as decimal separator)
return format.format(value)
}
fun stringToDouble(value: String): Double {
val format = DecimalFormat("#.####################") // Use the same pattern to ensure correct parsing
format.decimalFormatSymbols = DecimalFormatSymbols(Locale.US) // Consistent locale
return format.parse(value).toDouble()
}
fun main() {
val doubleValue = 12345.6789
val stringValue = doubleToString(doubleValue)
println("Double to String: $stringValue") // 12345.6789
val parsedValue = stringToDouble(stringValue)
println("String to Double: $parsedValue") // 12345.6789
}