I'd like to format following numbers into the numbers next to them with Android:
1000 to 1k 5821 to 5.8k 2000000 to 2m 7800000 to 7.8m
I'd like to format following numbers into the numbers next to them with Android:
1000 to 1k 5821 to 5.8k 2000000 to 2m 7800000 to 7.8m
Function
public String prettyCount(Number number) {
char[] suffix = {' ', 'k', 'M', 'B', 'T', 'P', 'E'};
long numValue = number.longValue();
int value = (int) Math.floor(Math.log10(numValue));
int base = value / 3;
if (value >= 3 && base < suffix.length) {
return new DecimalFormat("#0.0").format(numValue / Math.pow(10, base * 3)) + suffix[base];
} else {
return new DecimalFormat("#,##0").format(numValue);
}
}
Use
prettyCount(789); Output: 789
prettyCount(5821); Output: 5.8k
prettyCount(101808); Output: 101.8k
prettyCount(7898562); Output: 7.9M
Try this method :
For Java
public static String formatNumber(long count) {
if (count < 1000) return "" + count;
int exp = (int) (Math.log(count) / Math.log(1000));
return String.format("%.1f %c", count / Math.pow(1000, exp),"kMGTPE".charAt(exp-1));
}
For Kotlin(Android)
fun getFormatedNumber(count: Long): String {
if (count < 1000) return "" + count
val exp = (ln(count.toDouble()) / ln(1000.0)).toInt()
return String.format("%.1f %c", count / 1000.0.pow(exp.toDouble()), "kMGTPE"[exp - 1])
}
This should do the trick
String numberString = "";
if (Math.abs(number / 1000000) > 1) {
numberString = (number / 1000000).toString() + "m";
} else if (Math.abs(number / 1000) > 1) {
numberString = (number / 1000).toString() + "k";
} else {
numberString = number.toString();
}
Try this trick:
private String numberCalculation(long number) {
if (number < 1000)
return "" + number;
int exp = (int) (Math.log(number) / Math.log(1000));
return String.format("%.1f %c", number / Math.pow(1000, exp), "kMGTPE".charAt(exp-1));
}
As of Android 7.0 (API 24), it is possible to use CompactDecimalFormat
.
For example :
private String convertNumber(int number, Locale locale) {
CompactDecimalFormat compactDecimalFormat =
CompactDecimalFormat.getInstance(locale, CompactDecimalFormat.CompactStyle.SHORT);
return compactDecimalFormat.format(number);
}
This class is also part of ICU v49 (https://unicode-org.github.io/icu-docs/apidoc/dev/icu4j/com/ibm/icu/text/CompactDecimalFormat.html).
Furthermore, as of Android 11 (API 30), it is possible to use NumberFormatter
.
This class is also part of ICU v60.
// Kotlin Version
fun countviews(count:Long): String{
val array = arrayOf(' ', 'k', 'M', 'B', 'T', 'P', 'E')
val value = Math.floor(Math.log10(count.toDouble())).toInt()
val base = value / 3
if (value >= 3 && base < array.size) {
return DecimalFormat("#0.0").format(count/ Math.pow(10.0, (base * 3).toDouble())) + array[base]
} else {
return DecimalFormat("#,##0").format(count)
}
}
I needed to implement the same solution and took a hint from one of the answer in this thread. It suggested to use NumberFormatter for Android API 30+.
This is what is working for me. Additional benefit of using NumberFromatter API is that it adds the appropriate suffix as per Locale. Notation.compactShort() is the one adding engineering notations (K, M, B, T)
/**
* Converts Number to appropriate rounded off format with max 1 decimal place
* e.g. 1345 --> 1.3K, 15555900 --> 15.6M
*/
private fun formatCount(number: Long) = NumberFormatter.with()
.notation(Notation.compactShort())
.decimal(NumberFormatter.DecimalSeparatorDisplay.ALWAYS)
.precision(Precision.fixedFraction(1))
.locale(Resources.getSystem().configuration.locales.get(0))
.format(number)
.toString()
This a Kotlin "extension on Double" that worked for me.
This also doesn't round the number:
fun Double.currencyCountWithSuffix(): String {
val suffixChars = "KMGTPE"
val formatter = DecimalFormat("###.#")
formatter.roundingMode = RoundingMode.DOWN
return if (this < 1000.0) formatter.format(this)
else {
val exp = (ln(this) / ln(1000.0)).toInt()
formatter.format(this / 1000.0.pow(exp.toDouble())) + suffixChars[exp - 1]
}
}
public static String prettyCount(Double number) {
DecimalFormat df = new DecimalFormat("#.#");
String numberString = "";
if (Math.abs(number / 1000000) >= 1) {
numberString = df.format(number / 1000000.0) + "m";
} else if (Math.abs(number / 1000.0) >= 1) {
numberString = df.format(number / 1000.0) + "k";
} else {
numberString = number.toString();
}
return numberString;
}
Summary of all answers
private val Long.shortNotation
get(): String {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val locale = AppCompatDelegate.getApplicationLocales()[0]
?: Resources.getSystem().configuration.locales.get(0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) NumberFormatter.with()
.notation(Notation.compactShort())
.locale(locale)
.format(this)
.toString()
else CompactDecimalFormat
.getInstance(locale, CompactDecimalFormat.CompactStyle.SHORT)
.format(this)
} else {
val base = 1_000f
if (this < base) return "$this"
val ratio = ln(this.toDouble()) / ln(base)
val exp = ratio.toInt()
val format = if (ratio % 1 * 3 < 1) "%.1f%c" else "%.0f%c"
@Suppress("SpellCheckingInspection")
String.format(format, this / base.pow(exp), "kMGTPE"[exp - 1])
}
}
Simple use this function for kotlin
fun formatNumber(number: Long): String {
val suffix = charArrayOf(' ', 'k', 'M', 'B', 'T', 'P', 'E')
val value = floor(log10(number.toDouble())).toInt()
val base = value / 3
val result = if (value >= 3 && base < suffix.size) {
DecimalFormat("#.#").format(
number / 10.0.pow((base * 3).toDouble())
) + suffix[base]
} else {
DecimalFormat("#,##0").format(number)
}
return result.convertToEnglishDigits()
}
This is a modified version of Sujith Manjavana answer.
here i have used DecimalFormat to control the integers after the decimal point.
long kil = 1000;
long meg = kil * 1000;
long gig = meg * 1000;
long ter = gig * 1000;
double bytes = 56789; // your integer. if you are using a String then --> double bytes = Double.parseDouble(56789);
DecimalFormat form = new DecimalFormat("0.0"); // you can also use 0.00 or 0.000
if ((bytes >= 0) && (bytes < kil)) {
String oneDecimal = form.format(bytes);
Toast.makeText(MainActivity.this, oneDecimal, Toast.LENGTH_LONG).show();
} else if ((bytes >= kil) && (bytes < meg)) {
String oneDecimal = form.format(bytes / kil);
Toast.makeText(MainActivity.this, oneDecimal+" K", Toast.LENGTH_LONG).show();
} else if ((bytes >= meg) && (bytes < gig)) {
String oneDecimal = form.format(bytes / meg);
Toast.makeText(MainActivity.this, oneDecimal+" M", Toast.LENGTH_LONG).show();
} else if ((bytes >= gig) && (bytes < ter)) {
String oneDecimal = form.format(bytes / gig);
Toast.makeText(MainActivity.this, oneDecimal+" B", Toast.LENGTH_LONG).show();
} else if (bytes >= ter) {
String oneDecimal = form.format(bytes / ter);
Toast.makeText(MainActivity.this, oneDecimal+" T", Toast.LENGTH_LONG).show();
} else {
String oneDecimal = form.format(bytes);
Toast.makeText(MainActivity.this, oneDecimal, Toast.LENGTH_LONG).show();
}