String to Float Convert with decimal point Kotlin - android

I have String with decimal points of value. When I convert the String value to Float like this
val i : String = "123.70"
val j = i.toFloat()
Log.e("Tag", "-->" + j)
the result printed is
Tag-->123.7
But, what I want is
Tag-->123.70
Is there any possible way to get my desired result?

You can simply use a String that takes a decimal and formats it to a specific amount of decimal places.
Example:
fun main() {
// you have a String with a decimal value
val i : String = "123.70"
// then you parse/convert it to a Float
val j : Float = i.toFloat()
// and then, you output the value of the Float in a specific format
println("%.2f".format(j))
}
This prints
123.70
which should be working in the LogCat as well:
Log.e("Tag", "-->%.2f".format(j))

internally it doesn't affect it is the same but if you want to show it as 2 decimal places you can use String.format("%.2f", number).
val number = 10.7086134
val rounded = String.format("%.3f", number) // rounds to 3 decimal places

Related

Format negative decimal number with extension kotlin

I have a simple problem for which I didn`t find a solution. I am having large negative number ex(-6763.98) what I want is something like this ex($-6.78K). A found a lot of solutions that work for positive numbers but none that work for negative. This is the code that I am having right now.
const val COUNT_DIVISOR = 1000
const val COUNT_DIVISOR_FLOAT = 1000.0
fun getFormattedNumber(count: Long): String {
if (count < COUNT_DIVISOR) return "" + count
val exp = (ln(count.toDouble()) / ln(COUNT_DIVISOR_FLOAT)).toInt()
return resources.getString(
R.string.decimal_format_long_number_price,
count / COUNT_DIVISOR_FLOAT.pow(exp.toDouble()), EXTENSION[exp - 1]
)
}
The natural logarithm is not defined for negative values so the function ln will return NaN (not a number) for negative inputs.
From ln Kotlin documentation.
Special cases:
ln(NaN) is NaN
ln(x) is NaN when x < 0.0
ln(+Inf) is +Inf
ln(0.0) is -Inf
You have to make sure that the input is always a positive value in order to calculate the exponent correctly.
val exp = (ln(abs(count.toDouble())) / ln(COUNT_DIVISOR_FLOAT)).toInt()
Another problem is the first if check, which returns the input value itself for all inputs smaller than COUNT_DIVISOR. You have to allow large negative inputs through there as well.
if (count > -COUNT_DIVISOR && count < COUNT_DIVISOR) return "" + count
All together
const val COUNT_DIVISOR = 1000
const val COUNT_DIVISOR_FLOAT = 1000.0
fun getFormattedNumber(count: Long): String {
if (count > -COUNT_DIVISOR && count < COUNT_DIVISOR) return "" + count
val exp = (ln(abs(count.toDouble())) / ln(COUNT_DIVISOR_FLOAT)).toInt()
return resources.getString(
R.string.decimal_format_long_number_price,
count / COUNT_DIVISOR_FLOAT.pow(exp.toDouble()), EXTENSION[exp - 1]
)
}
If you want the result to always have 2 decimal places, consider any of these
val result = count / COUNT_DIVISOR_FLOAT.pow(exp.toDouble())
// This will use the root language/region neutral locale
// it will use the dot '.' as the decimal separator
"%.2f".format(Locale.ROOT, result)
// This will use the default locale
// it will use '.' or ',' as the decimal separator, based on the user settings on the target system
"%.2f".format(result)
val localeDefinedByYou = ... // or define a specific locale
"%.2f".format(localeDefinedByYou, result)

How can I round this result to 2 decimal places code example

How can i round off this particular code to show only 2 decimal places.
double sum = ((3.141592654/4*(tbmODInput)*(tbmODInput))-(3.141592654/4*(pipeODInput)*(pipeODInput)))*muckUpInput;
volume_per_meter_result.setText(String.valueOf(sum));
Kotlin
val value = 3.14159265358979323
// round to 2 decimal: 3.14
val formated = "Rounded is: %.2f".format(value)
Java
double value = 3.14159265358979323;
// round to 2 decimal: 3.14
String formated = String.format("Rounded is: %.2f", value);
For Java:
double value = 3.141592654;
String formated = String.format("Rounded is: %.2f", value);
For Kotlin:
val value = 3.141592654
val formattedText= "Rounded is: %.2f".format(value)

Need to round off two points after decimal digit

I'm working on an app and facing an issue. I've tried a number of solutions but nothing solved my problem.
I need to round off two digits after decimal point.
For Example.
9.225 should be rounded off to 9.23
Thank you.
For Kotlin use "%.2f".format(number), for Java use String.format("%.2f", number)
Result:
You can use String.format("%.2f", d), this will rounded automatically. d is your value.
OR
You can use this
double d = 1.234567;
DecimalFormat df = new DecimalFormat("#.##");
Log.d(df.format(d));
You can get as a float value as well like below.
float value = Float.valueOf(df.format(d)); // Output will be 1.24
I would have gone with a probable over the top solution however this is what i came up with.
It uses regex to split the string value of the number passed and then rounds up/down depending on the leading digit after the decimal place. It will return a Double in the instance but you can change that if you like. It does throw IllegalArgumentException, but thats taste dependant.
/**
* #param value the value that is being transformed
* #param decimalPlace the decimal place you want to return to
* #return transformed value to the decimal place
* #throws IllegalArgumentException
*/
Double roundNumber(#NonNull Double value, #NonNull Integer decimalPlace) throws IllegalArgumentException {
String valueString = value.toString();
if(valueString.length()> decimalPlace+1){
throw new IllegalArgumentException(String.format("The string value of %s is not long enough to have %dplaces", valueString, decimalPlace));
}
Pattern pattern = Pattern.compile("(\\d)('.')(\\d)");
Matcher matcher = pattern.matcher(valueString);
if (matcher.groupCount() != 4) { //0 = entire pattern, so 4 should be the total ?
throw new IllegalArgumentException(String.format("The string value of %s does not contain three groups.", valueString));
}
String decimal = matcher.group(3);
int place = decimal.charAt(decimalPlace);
int afterDecimalPlace = decimal.charAt(decimalPlace + 1);
String newDecimal = decimal.substring(0, decimalPlace - 1);
newDecimal += afterDecimalPlace > 5 ? (place + 1) : place;
return Double.parseDouble(matcher.group(1) + "." + newDecimal);
}

Kotlin float number with 2 decimals to string without precision loss

In Android-Kotlin I am getting float number from backend (for example num = 10000000.47)
When I try to String.format it and add that number in my balanceTextview it shows it with exponent (something like 1.0E10).
I want to show number normally without exponent and with 2 decimals. (Without presicion loss!)
Tried to use DecimalFormat("#.##") but it didn't help me. Maybe I'm doing something wrong?
num = 10000000.47f
val dec = DecimalFormat("#.##")
var result = dec.format(num)
my result is: 10000000
It losts my decimal places
The issue is your number type. According to the documentation:
For variables initialized with fractional numbers, the compiler infers the Double type. To explicitly specify the Float type for a value, add the suffix f or F. If such a value contains more than 6-7 decimal digits, it will be rounded.
With an example that shows how information may get lost:
val pi = 3.14 // Double
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float, actual value is 2.7182817
If the value is specified as Double instead of Float, i.e.
val num = 10000000.47
instead of
val num = 10000000.47f
then your approach works as expected, but could be shortened to:
"%.2f".format(num)
(note that the shorter version will also print "100" as "100.00" which is different from your approach but potentially still desired behaviour)
If you receive a Float from the backend then the information is already lost on your side. Otherwise you should be able to fix the issue by improved parsing.
The extension function format is only available in the JVM. In Kotlin/native, you can use this instead:
fun Float.toPrecision(precision: Int) =
this.toDouble().toPrecision(precision)
fun Double.toPrecision(precision: Int) =
if (precision < 1) {
"${this.roundToInt()}"
} else {
val p = 10.0.pow(precision)
val v = (abs(this) * p).roundToInt()
val i = floor(v / p)
var f = "${floor(v - (i * p)).toInt()}"
while (f.length < precision) f = "0$f"
val s = if (this < 0) "-" else ""
"$s${i.toInt()}.$f"
}

Kotlin: SumbyDouble returning additional decimals

I am summing double value from arraylist its giving additional decimals as 99999, how to fix this, please guide
ex
class ExDet{var expName:String ="",var expAmount:Double = 0.0}
val arrayList = ArrayList<ExDet>()
arrayList.add(ExDet("Abc 1",45.66))
arrayList.add(ExDet("DEF 1",10.0))
arrayList.add(ExDet("Lee 1",600.89))
arrayList.add(ExDet("Ifr 1",200.9))
var amt = arrayList.sumByDouble{ it.expAmount }
Expected Value of Amount is :
Amt = 857.45
But it returns
Amt = 857.4499999
Sample Code to Test
data class ExDet(var expName:String ="" ,var expAmount:Double=0.0)
fun main(args: Array<String>) {
val arrayList = ArrayList<ExDet>()
arrayList.add(ExDet("Abc 1",45.66))
arrayList.add(ExDet("DEF 1",10.0))
arrayList.add(ExDet("Lee 1",600.89))
arrayList.add(ExDet("Ifr 1",200.9))
var amt = arrayList.sumByDouble{ it.expAmount }
println("Amount is : $amt")
}
The issue you are confronted with is that floating point numbers are build on top of base 2, not base 10.
Think how you can easily represent a third as a fraction (1/3), but when you convert to decimal you get a repeating (recurring) number after the radix point (i.e. 0.33...). Some decimal numbers are recurring when represented in base-2, e.g. x.9. The computer has a finite number of bits, so the (base-2) number is truncated. All the truncation errors can add up.
You need to round to the required precision (e.g. round(x * 100) / 100).
If you are only interested in how it is displayed then you can use the format function with something like "%.2f".
String.format("%.2f", value)

Categories

Resources