Mat*_* B. 150 java number-formatting
我想将以下数字格式化为java旁边的数字:
1000 to 1k
5821 to 5.8k
10500 to 10k
101800 to 101k
2000000 to 2m
7800000 to 7.8m
92150000 to 92m
123200000 to 123m
Run Code Online (Sandbox Code Playgroud)
右边的数字是长整数,左边的数字是字符串.我应该如何处理这个问题.我已经为此做了很少的算法,但我认为可能已经发明了一些可以做得更好的事情,并且如果我开始处理数十亿和数万亿,则不需要额外的测试:)
其他要求:
ass*_*ias 143
这是一个适用于任何长值的解决方案,我发现它非常易读(核心逻辑在方法的最后三行完成format).
它利用它TreeMap来找到合适的后缀.令人惊讶的是,它比我之前编写的使用数组的解决方案更有效,并且更难以阅读.
private static final NavigableMap<Long, String> suffixes = new TreeMap<> ();
static {
suffixes.put(1_000L, "k");
suffixes.put(1_000_000L, "M");
suffixes.put(1_000_000_000L, "G");
suffixes.put(1_000_000_000_000L, "T");
suffixes.put(1_000_000_000_000_000L, "P");
suffixes.put(1_000_000_000_000_000_000L, "E");
}
public static String format(long value) {
//Long.MIN_VALUE == -Long.MIN_VALUE so we need an adjustment here
if (value == Long.MIN_VALUE) return format(Long.MIN_VALUE + 1);
if (value < 0) return "-" + format(-value);
if (value < 1000) return Long.toString(value); //deal with easy case
Entry<Long, String> e = suffixes.floorEntry(value);
Long divideBy = e.getKey();
String suffix = e.getValue();
long truncated = value / (divideBy / 10); //the number part of the output times 10
boolean hasDecimal = truncated < 100 && (truncated / 10d) != (truncated / 10);
return hasDecimal ? (truncated / 10d) + suffix : (truncated / 10) + suffix;
}
Run Code Online (Sandbox Code Playgroud)
public static void main(String args[]) {
long[] numbers = {0, 5, 999, 1_000, -5_821, 10_500, -101_800, 2_000_000, -7_800_000, 92_150_000, 123_200_000, 9_999_999, 999_999_999_999_999_999L, 1_230_000_000_000_000L, Long.MIN_VALUE, Long.MAX_VALUE};
String[] expected = {"0", "5", "999", "1k", "-5.8k", "10k", "-101k", "2M", "-7.8M", "92M", "123M", "9.9M", "999P", "1.2P", "-9.2E", "9.2E"};
for (int i = 0; i < numbers.length; i++) {
long n = numbers[i];
String formatted = format(n);
System.out.println(n + " => " + formatted);
if (!formatted.equals(expected[i])) throw new AssertionError("Expected: " + expected[i] + " but found: " + formatted);
}
}
Run Code Online (Sandbox Code Playgroud)
Eli*_*ine 98
我知道,这看起来更像是一个C程序,但它超轻量级!
public static void main(String args[]) {
long[] numbers = new long[]{1000, 5821, 10500, 101800, 2000000, 7800000, 92150000, 123200000, 9999999};
for(long n : numbers) {
System.out.println(n + " => " + coolFormat(n, 0));
}
}
private static char[] c = new char[]{'k', 'm', 'b', 't'};
/**
* Recursive implementation, invokes itself for each factor of a thousand, increasing the class on each invokation.
* @param n the number to format
* @param iteration in fact this is the class from the array c
* @return a String representing the number n formatted in a cool looking way.
*/
private static String coolFormat(double n, int iteration) {
double d = ((long) n / 100) / 10.0;
boolean isRound = (d * 10) %10 == 0;//true if the decimal part is equal to 0 (then it's trimmed anyway)
return (d < 1000? //this determines the class, i.e. 'k', 'm' etc
((d > 99.9 || isRound || (!isRound && d > 9.99)? //this decides whether to trim the decimals
(int) d * 10 / 10 : d + "" // (int) d * 10 / 10 drops the decimal
) + "" + c[iteration])
: coolFormat(d, iteration+1));
}
Run Code Online (Sandbox Code Playgroud)
它输出:
1000 => 1k
5821 => 5.8k
10500 => 10k
101800 => 101k
2000000 => 2m
7800000 => 7.8m
92150000 => 92m
123200000 => 123m
9999999 => 9.9m
Run Code Online (Sandbox Code Playgroud)
jzd*_*jzd 42
这里是一个使用DecimalFormat工程符号的解决方案:
public static void main(String args[]) {
long[] numbers = new long[]{7, 12, 856, 1000, 5821, 10500, 101800, 2000000, 7800000, 92150000, 123200000, 9999999};
for(long number : numbers) {
System.out.println(number + " = " + format(number));
}
}
private static String[] suffix = new String[]{"","k", "m", "b", "t"};
private static int MAX_LENGTH = 4;
private static String format(double number) {
String r = new DecimalFormat("##0E0").format(number);
r = r.replaceAll("E[0-9]", suffix[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]);
while(r.length() > MAX_LENGTH || r.matches("[0-9]+\\.[a-z]")){
r = r.substring(0, r.length()-2) + r.substring(r.length() - 1);
}
return r;
}
Run Code Online (Sandbox Code Playgroud)
输出:
7 = 7
12 = 12
856 = 856
1000 = 1k
5821 = 5.8k
10500 = 10k
101800 = 102k
2000000 = 2m
7800000 = 7.8m
92150000 = 92m
123200000 = 123m
9999999 = 10m
Run Code Online (Sandbox Code Playgroud)
jhu*_*ado 21
需要一些改进,但是:StrictMath来救援!
您可以将后缀放在String或数组中,并根据power或其他类似内容获取fetch'em.
该部门也可以围绕权力进行管理,我认为几乎所有事情都与权力价值有关.希望能帮助到你!
public static String formatValue(double value) {
int power;
String suffix = " kmbt";
String formattedNumber = "";
NumberFormat formatter = new DecimalFormat("#,###.#");
power = (int)StrictMath.log10(value);
value = value/(Math.pow(10,(power/3)*3));
formattedNumber=formatter.format(value);
formattedNumber = formattedNumber + suffix.charAt(power/3);
return formattedNumber.length()>4 ? formattedNumber.replaceAll("\\.[0-9]+", "") : formattedNumber;
}
Run Code Online (Sandbox Code Playgroud)
输出:
999
1.2K
98K
911k
1.1米
11B
712B
34吨
Dón*_*nal 15
该解决方案(本答案的扩展)解决了上述问题.
import org.apache.commons.lang.math.NumberUtils;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.regex.Pattern;
/**
* Converts a number to a string in <a href="http://en.wikipedia.org/wiki/Metric_prefix">metric prefix</a> format.
* For example, 7800000 will be formatted as '7.8M'. Numbers under 1000 will be unchanged. Refer to the tests for further examples.
*/
class RoundedMetricPrefixFormat extends Format {
private static final String[] METRIC_PREFIXES = new String[]{"", "k", "M", "G", "T"};
/**
* The maximum number of characters in the output, excluding the negative sign
*/
private static final Integer MAX_LENGTH = 4;
private static final Pattern TRAILING_DECIMAL_POINT = Pattern.compile("[0-9]+\\.[kMGT]");
private static final Pattern METRIC_PREFIXED_NUMBER = Pattern.compile("\\-?[0-9]+(\\.[0-9])?[kMGT]");
@Override
public StringBuffer format(Object obj, StringBuffer output, FieldPosition pos) {
Double number = Double.valueOf(obj.toString());
// if the number is negative, convert it to a positive number and add the minus sign to the output at the end
boolean isNegative = number < 0;
number = Math.abs(number);
String result = new DecimalFormat("##0E0").format(number);
Integer index = Character.getNumericValue(result.charAt(result.length() - 1)) / 3;
result = result.replaceAll("E[0-9]", METRIC_PREFIXES[index]);
while (result.length() > MAX_LENGTH || TRAILING_DECIMAL_POINT.matcher(result).matches()) {
int length = result.length();
result = result.substring(0, length - 2) + result.substring(length - 1);
}
return output.append(isNegative ? "-" + result : result);
}
/**
* Convert a String produced by <tt>format()</tt> back to a number. This will generally not restore
* the original number because <tt>format()</tt> is a lossy operation, e.g.
*
* <pre>
* {@code
* def formatter = new RoundedMetricPrefixFormat()
* Long number = 5821L
* String formattedNumber = formatter.format(number)
* assert formattedNumber == '5.8k'
*
* Long parsedNumber = formatter.parseObject(formattedNumber)
* assert parsedNumber == 5800
* assert parsedNumber != number
* }
* </pre>
*
* @param source a number that may have a metric prefix
* @param pos if parsing succeeds, this should be updated to the index after the last parsed character
* @return a Number if the the string is a number without a metric prefix, or a Long if it has a metric prefix
*/
@Override
public Object parseObject(String source, ParsePosition pos) {
if (NumberUtils.isNumber(source)) {
// if the value is a number (without a prefix) don't return it as a Long or we'll lose any decimals
pos.setIndex(source.length());
return toNumber(source);
} else if (METRIC_PREFIXED_NUMBER.matcher(source).matches()) {
boolean isNegative = source.charAt(0) == '-';
int length = source.length();
String number = isNegative ? source.substring(1, length - 1) : source.substring(0, length - 1);
String metricPrefix = Character.toString(source.charAt(length - 1));
Number absoluteNumber = toNumber(number);
int index = 0;
for (; index < METRIC_PREFIXES.length; index++) {
if (METRIC_PREFIXES[index].equals(metricPrefix)) {
break;
}
}
Integer exponent = 3 * index;
Double factor = Math.pow(10, exponent);
factor *= isNegative ? -1 : 1;
pos.setIndex(source.length());
Float result = absoluteNumber.floatValue() * factor.longValue();
return result.longValue();
}
return null;
}
private static Number toNumber(String number) {
return NumberUtils.createNumber(number);
}
}
Run Code Online (Sandbox Code Playgroud)
该解决方案最初是用Groovy编写的,如下所示.
import org.apache.commons.lang.math.NumberUtils
import java.text.DecimalFormat
import java.text.FieldPosition
import java.text.Format
import java.text.ParsePosition
import java.util.regex.Pattern
/**
* Converts a number to a string in <a href="http://en.wikipedia.org/wiki/Metric_prefix">metric prefix</a> format.
* For example, 7800000 will be formatted as '7.8M'. Numbers under 1000 will be unchanged. Refer to the tests for further examples.
*/
class RoundedMetricPrefixFormat extends Format {
private static final METRIC_PREFIXES = ["", "k", "M", "G", "T"]
/**
* The maximum number of characters in the output, excluding the negative sign
*/
private static final Integer MAX_LENGTH = 4
private static final Pattern TRAILING_DECIMAL_POINT = ~/[0-9]+\.[kMGT]/
private static final Pattern METRIC_PREFIXED_NUMBER = ~/\-?[0-9]+(\.[0-9])?[kMGT]/
@Override
StringBuffer format(Object obj, StringBuffer output, FieldPosition pos) {
Double number = obj as Double
// if the number is negative, convert it to a positive number and add the minus sign to the output at the end
boolean isNegative = number < 0
number = Math.abs(number)
String result = new DecimalFormat("##0E0").format(number)
Integer index = Character.getNumericValue(result.charAt(result.size() - 1)) / 3
result = result.replaceAll("E[0-9]", METRIC_PREFIXES[index])
while (result.size() > MAX_LENGTH || TRAILING_DECIMAL_POINT.matcher(result).matches()) {
int length = result.size()
result = result.substring(0, length - 2) + result.substring(length - 1)
}
output << (isNegative ? "-$result" : result)
}
/**
* Convert a String produced by <tt>format()</tt> back to a number. This will generally not restore
* the original number because <tt>format()</tt> is a lossy operation, e.g.
*
* <pre>
* {@code
* def formatter = new RoundedMetricPrefixFormat()
* Long number = 5821L
* String formattedNumber = formatter.format(number)
* assert formattedNumber == '5.8k'
*
* Long parsedNumber = formatter.parseObject(formattedNumber)
* assert parsedNumber == 5800
* assert parsedNumber != number
* }
* </pre>
*
* @param source a number that may have a metric prefix
* @param pos if parsing succeeds, this should be updated to the index after the last parsed character
* @return a Number if the the string is a number without a metric prefix, or a Long if it has a metric prefix
*/
@Override
Object parseObject(String source, ParsePosition pos) {
if (source.isNumber()) {
// if the value is a number (without a prefix) don't return it as a Long or we'll lose any decimals
pos.index = source.size()
toNumber(source)
} else if (METRIC_PREFIXED_NUMBER.matcher(source).matches()) {
boolean isNegative = source[0] == '-'
String number = isNegative ? source[1..-2] : source[0..-2]
String metricPrefix = source[-1]
Number absoluteNumber = toNumber(number)
Integer exponent = 3 * METRIC_PREFIXES.indexOf(metricPrefix)
Long factor = 10 ** exponent
factor *= isNegative ? -1 : 1
pos.index = source.size()
(absoluteNumber * factor) as Long
}
}
private static Number toNumber(String number) {
NumberUtils.createNumber(number)
}
}
Run Code Online (Sandbox Code Playgroud)
测试是用Groovy编写的,但可用于验证Java或Groovy类(因为它们都具有相同的名称和API).
import java.text.Format
import java.text.ParseException
class RoundedMetricPrefixFormatTests extends GroovyTestCase {
private Format roundedMetricPrefixFormat = new RoundedMetricPrefixFormat()
void testNumberFormatting() {
[
7L : '7',
12L : '12',
856L : '856',
1000L : '1k',
(-1000L) : '-1k',
5821L : '5.8k',
10500L : '10k',
101800L : '102k',
2000000L : '2M',
7800000L : '7.8M',
(-7800000L): '-7.8M',
92150000L : '92M',
123200000L : '123M',
9999999L : '10M',
(-9999999L): '-10M'
].each { Long rawValue, String expectedRoundValue ->
assertEquals expectedRoundValue, roundedMetricPrefixFormat.format(rawValue)
}
}
void testStringParsingSuccess() {
[
'7' : 7,
'8.2' : 8.2F,
'856' : 856,
'-856' : -856,
'1k' : 1000,
'5.8k' : 5800,
'-5.8k': -5800,
'10k' : 10000,
'102k' : 102000,
'2M' : 2000000,
'7.8M' : 7800000L,
'92M' : 92000000L,
'-92M' : -92000000L,
'123M' : 123000000L,
'10M' : 10000000L
].each { String metricPrefixNumber, Number expectedValue ->
def parsedNumber = roundedMetricPrefixFormat.parseObject(metricPrefixNumber)
assertEquals expectedValue, parsedNumber
}
}
void testStringParsingFail() {
shouldFail(ParseException) {
roundedMetricPrefixFormat.parseObject('notNumber')
}
}
}
Run Code Online (Sandbox Code Playgroud)
Lan*_*dei 12
在ICU LIB有数字的一个基于规则的格式,可我认为使用ICU会给你一个可读和maintanable解决方案可用于数字spellout等.
[用法]
正确的类是RuleBasedNumberFormat.格式本身可以存储为单独的文件(或String常量,IIRC).
来自http://userguide.icu-project.org/formatparse/numbers的示例
double num = 2718.28;
NumberFormat formatter =
new RuleBasedNumberFormat(RuleBasedNumberFormat.SPELLOUT);
String result = formatter.format(num);
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)
同一页面显示罗马数字,所以我想你的情况也应该是可能的.
我将大数转换为小数的函数(2 位数字)。您可以通过改变而改变的位数#.##中DecimalFormat
public String formatValue(float value) {
String arr[] = {"", "K", "M", "B", "T", "P", "E"};
int index = 0;
while ((value / 1000) >= 1) {
value = value / 1000;
index++;
}
DecimalFormat decimalFormat = new DecimalFormat("#.##");
return String.format("%s %s", decimalFormat.format(value), arr[index]);
}
Run Code Online (Sandbox Code Playgroud)
测试
System.out.println(formatValue(100)); // 100
System.out.println(formatValue(1000)); // 1 K
System.out.println(formatValue(10345)); // 10.35 K
System.out.println(formatValue(10012)); // 10.01 K
System.out.println(formatValue(123456)); // 123.46 K
System.out.println(formatValue(4384324)); // 4.38 M
System.out.println(formatValue(10000000)); // 10 M
System.out.println(formatValue(Long.MAX_VALUE)); // 9.22 E
Run Code Online (Sandbox Code Playgroud)
希望有帮助
重要提示:double对于数字而言99999999999999999L,为了使用标准而返回的铸件将失败,100P而不是99P因为double使用IEEE标准:
如果具有最多15位有效数字的十进制字符串转换为IEEE 754双精度表示,然后转换回具有相同有效位数的字符串,则最终字符串应与原始字符串匹配.[
long有多达19位有效数字.]
System.out.println((long)(double)99999999999999992L); // 100000000000000000
System.out.println((long)(double)99999999999999991L); // 99999999999999984
// it is even worse for the logarithm:
System.out.println(Math.log10(99999999999999600L)); // 17.0
System.out.println(Math.log10(99999999999999500L)); // 16.999999999999996
Run Code Online (Sandbox Code Playgroud)
此解决方案可以切断不需要的数字,适用于所有long值.简单但高性能的实现(下面的比较).-120k不能用4个字符表示,即使-0.1M太长,这就是为什么负数5个字符必须是好的:
private static final char[] magnitudes = {'k', 'M', 'G', 'T', 'P', 'E'}; // enough for long
public static final String convert(long number) {
String ret;
if (number >= 0) {
ret = "";
} else if (number <= -9200000000000000000L) {
return "-9.2E";
} else {
ret = "-";
number = -number;
}
if (number < 1000)
return ret + number;
for (int i = 0; ; i++) {
if (number < 10000 && number % 1000 >= 100)
return ret + (number / 1000) + '.' + ((number % 1000) / 100) + magnitudes[i];
number /= 1000;
if (number < 1000)
return ret + number + magnitudes[i];
}
}
Run Code Online (Sandbox Code Playgroud)
else if在开始时的测试是必要的,因为最小值是-(2^63)最大值(2^63)-1,因此number = -number如果分配将失败number == Long.MIN_VALUE.如果我们必须进行检查,那么我们也可以包括尽可能多的数字,而不仅仅是检查number == Long.MIN_VALUE.
将这种实现与得到最多投票者(据称是目前最快的)进行比较表明它的速度提高了5倍以上(这取决于测试设置,但是随着数字越多,增益越大,这种实现方式越多做更多的检查,因为它处理所有情况,所以如果另一个将被修复,差异将变得更大).它是快速的,因为没有浮点运算,没有对数,没有幂,没有递归,没有正则表达式,没有复杂的格式化程序和最小化创建的对象数量.
这是测试程序:
public class Test {
public static void main(String[] args) {
long[] numbers = new long[20000000];
for (int i = 0; i < numbers.length; i++)
numbers[i] = Math.random() < 0.5 ? (long) (Math.random() * Long.MAX_VALUE) : (long) (Math.random() * Long.MIN_VALUE);
System.out.println(convert1(numbers) + " vs. " + convert2(numbers));
}
private static long convert1(long[] numbers) {
long l = System.currentTimeMillis();
for (int i = 0; i < numbers.length; i++)
Converter1.convert(numbers[i]);
return System.currentTimeMillis() - l;
}
private static long convert2(long[] numbers) {
long l = System.currentTimeMillis();
for (int i = 0; i < numbers.length; i++)
Converter2.coolFormat(numbers[i], 0);
return System.currentTimeMillis() - l;
}
}
Run Code Online (Sandbox Code Playgroud)
可能的输出:( 2309 vs. 11591当只使用正数时大致相同,在反转执行顺序时更加极端,可能与垃圾收集有关)
这是一个没有递归的简短实现,只是一个非常小的循环.与负数不工作,但支持所有积极long到s Long.MAX_VALUE:
private static final char[] SUFFIXES = {'k', 'm', 'g', 't', 'p', 'e' };
public static String format(long number) {
if(number < 1000) {
// No need to format this
return String.valueOf(number);
}
// Convert to a string
final String string = String.valueOf(number);
// The suffix we're using, 1-based
final int magnitude = (string.length() - 1) / 3;
// The number of digits we must show before the prefix
final int digits = (string.length() - 1) % 3 + 1;
// Build the string
char[] value = new char[4];
for(int i = 0; i < digits; i++) {
value[i] = string.charAt(i);
}
int valueLength = digits;
// Can and should we add a decimal point and an additional number?
if(digits == 1 && string.charAt(1) != '0') {
value[valueLength++] = '.';
value[valueLength++] = string.charAt(1);
}
value[valueLength++] = SUFFIXES[magnitude - 1];
return new String(value, 0, valueLength);
}
Run Code Online (Sandbox Code Playgroud)
输出:
1k
5.8k
10k
101k
2m
7.8m
92m
123m
9.2e(这是Long.MAX_VALUE)
我还做了一些非常简单的基准测试(格式化1000万随机长片),它比Elijah的实现速度快得多,并且比assylias的实现快一点.
我的:1137.028 ms
Elijah:2664.396 ms
assylias':1373.473 ms
在JDK / 12及更高版本中,您现在可以使用NumberFormat.getCompactNumberInstance格式化数字。您可以创建NumberFormat第一个
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
Run Code Online (Sandbox Code Playgroud)
然后将其用于format:
Run Code Online (Sandbox Code Playgroud)fmt.format(1000) $5 ==> "1K" fmt.format(10000000) $9 ==> "10M" fmt.format(1000000000) $11 ==> "1B"
以下代码显示了如何通过轻松扩展来实现此目的.
"魔法"主要在于makeDecimal函数,对于传入的正确值,它保证输出中永远不会有超过四个字符.
它首先提取给定除数的整数和十分之一部分,因此,例如,12,345,678除数1,000,000将给出whole值12和tenths值3.
从那以后,它可以决定是使用规则输出整个部分还是整个部分和十分之一部分:
代码如下:
static private String makeDecimal(long val, long div, String sfx) {
val = val / (div / 10);
long whole = val / 10;
long tenths = val % 10;
if ((tenths == 0) || (whole >= 10))
return String.format("%d%s", whole, sfx);
return String.format("%d.%d%s", whole, tenths, sfx);
}
Run Code Online (Sandbox Code Playgroud)
然后,使用正确的值调用辅助函数是一件简单的事情,包括一些使开发人员更容易生活的常量:
static final long THOU = 1000L;
static final long MILL = 1000000L;
static final long BILL = 1000000000L;
static final long TRIL = 1000000000000L;
static final long QUAD = 1000000000000000L;
static final long QUIN = 1000000000000000000L;
static private String Xlat(long val) {
if (val < THOU) return Long.toString(val);
if (val < MILL) return makeDecimal(val, THOU, "k");
if (val < BILL) return makeDecimal(val, MILL, "m");
if (val < TRIL) return makeDecimal(val, BILL, "b");
if (val < QUAD) return makeDecimal(val, TRIL, "t");
if (val < QUIN) return makeDecimal(val, QUAD, "q");
return makeDecimal(val, QUIN, "u");
}
Run Code Online (Sandbox Code Playgroud)
makeDecimal函数执行繁琐的工作这一事实意味着扩展范围999,999,999仅仅是添加额外的一行Xlat,我很容易为你完成.
最后return的Xlat,因为你可以在一个64位保持最大值签订了只有大约9.2百万兆不需要条件.
但是,如果根据一些奇怪的要求,Oracle决定添加128位longer类型或1024位damn_long类型,那么你将为它做好准备:-)
最后,您可以使用一些小测试工具来验证功能.
public static void main(String[] args) {
long vals[] = {
999L, 1000L, 5821L, 10500L, 101800L, 2000000L,
7800000L, 92150000L, 123200000L, 999999999L,
1000000000L, 1100000000L, 999999999999L,
1000000000000L, 999999999999999L,
1000000000000000L, 9223372036854775807L
};
for (long val: vals)
System.out.println ("" + val + " -> " + Xlat(val));
}
}
Run Code Online (Sandbox Code Playgroud)
您可以从输出中看到它为您提供所需的内容:
999 -> 999
1000 -> 1k
5821 -> 5.8k
10500 -> 10k
101800 -> 101k
2000000 -> 2m
7800000 -> 7.8m
92150000 -> 92m
123200000 -> 123m
999999999 -> 999m
1000000000 -> 1b
1100000000 -> 1.1b
999999999999 -> 999b
1000000000000 -> 1t
999999999999999 -> 999t
1000000000000000 -> 1q
9223372036854775807 -> 9.2u
Run Code Online (Sandbox Code Playgroud)
而且,顺便说一句,请注意,将负数传递给此函数将导致字符串太长,无法满足您的要求,因为它遵循
< THOU路径).我认为这没关系,因为你只在问题中提到了非负值.
小智 7
对于任何想要回合的人.这是一个很好的,易于阅读的解决方案,它利用了Java.Lang.Math库
public static String formatNumberExample(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);
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
我不知道这是不是最好的方法,但这就是我所做的.
7=>7
12=>12
856=>856
1000=>1.0k
5821=>5.82k
10500=>10.5k
101800=>101.8k
2000000=>2.0m
7800000=>7.8m
92150000=>92.15m
123200000=>123.2m
9999999=>10.0m
Run Code Online (Sandbox Code Playgroud)
---代码---
public String Format(Integer number){
String[] suffix = new String[]{"k","m","b","t"};
int size = (number.intValue() != 0) ? (int) Math.log10(number) : 0;
if (size >= 3){
while (size % 3 != 0) {
size = size - 1;
}
}
double notation = Math.pow(10, size);
String result = (size >= 3) ? + (Math.round((number / notation) * 100) / 100.0d)+suffix[(size/3) - 1] : + number + "";
return result
}
Run Code Online (Sandbox Code Playgroud)
小智 6
这是我的代码。干净简单。
public static String getRoughNumber(long value) {
if (value <= 999) {
return String.valueOf(value);
}
final String[] units = new String[]{"", "K", "M", "B", "P"};
int digitGroups = (int) (Math.log10(value) / Math.log10(1000));
return new DecimalFormat("#,##0.#").format(value / Math.pow(1000, digitGroups)) + "" + units[digitGroups];
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我的Java生疏了,但这是我在C#中实现它的方式:
private string FormatNumber(double value)
{
string[] suffixes = new string[] {" k", " m", " b", " t", " q"};
for (int j = suffixes.Length; j > 0; j--)
{
double unit = Math.Pow(1000, j);
if (value >= unit)
return (value / unit).ToString("#,##0.0") + suffixes[--j];
}
return value.ToString("#,##0");
}
Run Code Online (Sandbox Code Playgroud)
调整它以使用CS公斤(1,024)而不是公制公斤,或添加更多单位很容易.它将1,000格式化为"1.0 k"而不是"1 k",但我相信这是无关紧要的.
为了满足更具体的要求"不超过四个字符",删除后缀之前的空格并调整中间块,如下所示:
if (value >= unit)
{
value /= unit;
return (value).ToString(value >= unit * 9.95 ? "#,##0" : "#,##0.0") + suffixes[--j];
}
Run Code Online (Sandbox Code Playgroud)
我的最爱.您可以使用"k"等作为十进制的指示符,这在电子域中很常见.这将为您提供额外的数字,而无需额外的空间
第二列尝试使用尽可能多的数字
1000 => 1.0k | 1000
5821 => 5.8k | 5821
10500 => 10k | 10k5
101800 => 101k | 101k
2000000 => 2.0m | 2m
7800000 => 7.8m | 7m8
92150000 => 92m | 92m1
123200000 => 123m | 123m
9999999 => 9.9m | 9m99
Run Code Online (Sandbox Code Playgroud)
这是代码
public class HTTest {
private static String[] unit = {"u", "k", "m", "g", "t"};
/**
* @param args
*/
public static void main(String[] args) {
int[] numbers = new int[]{1000, 5821, 10500, 101800, 2000000, 7800000, 92150000, 123200000, 9999999};
for(int n : numbers) {
System.out.println(n + " => " + myFormat(n) + " | " + myFormat2(n));
}
}
private static String myFormat(int pN) {
String str = Integer.toString(pN);
int len = str.length ()-1;
if (len <= 3) return str;
int level = len / 3;
int mode = len % 3;
switch (mode) {
case 0: return str.substring(0, 1) + "." + str.substring(1, 2) + unit[level];
case 1: return str.substring(0, 2) + unit[level];
case 2: return str.substring(0, 3) + unit[level];
}
return "how that?";
}
private static String trim1 (String pVal) {
if (pVal.equals("0")) return "";
return pVal;
}
private static String trim2 (String pVal) {
if (pVal.equals("00")) return "";
return pVal.substring(0, 1) + trim1(pVal.substring(1,2));
}
private static String myFormat2(int pN) {
String str = Integer.toString(pN);
int len = str.length () - 1;
if (len <= 3) return str;
int level = len / 3;
int mode = len % 3;
switch (mode) {
case 0: return str.substring(0, 1) + unit[level] + trim2(str.substring(1, 3));
case 2: return str.substring(0, 3) + unit[level];
case 1: return str.substring(0, 2) + unit[level] + trim1(str.substring(2, 3));
}
return "how that?";
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50147 次 |
| 最近记录: |