programing

Java에서 1200~1.2k 포맷하는 방법

goodcopy 2022. 7. 3. 23:13
반응형

Java에서 1200~1.2k 포맷하는 방법

다음 숫자의 서식을 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

오른쪽 숫자는 길거나 정수이며 왼쪽 숫자는 문자열입니다.어떻게 접근해야 할까요?저는 이미 이 알고리즘을 거의 실행하지 않았습니다만, 이 알고리즘에 대해 더 나은 작업을 할 수 있고 수십억, 수조 개의 알고리즘을 사용하기 시작하면 추가 테스트가 필요하지 않은 발명품이 이미 출시되어 있을지도 모른다고 생각했습니다.

기타 요건:

  • 형식은 최대 4자여야 합니다.
  • 위의 의미는 1.1k는 OK이며, 11.2k는 OK가 아닙니다.7.8m도 OK 19.1m도 OK 아니다.소수점 앞의 한 자리 숫자만 소수점을 가질 수 있습니다.소수점 앞의 두 자리는 소수점 이후의 자리가 아님을 의미합니다.
  • 반올림은 필요 없습니다.(k와 m이 부가된 숫자는 논리 정밀한 기사가 아니라 근사치를 나타내는 아날로그 게이지에 가깝습니다.따라서 반올림은 캐시된 결과를 보고 있는 동안에도 여러 자리 수를 늘리거나 지정할 수 있는 변수의 특성 때문에 관련이 없습니다.)

여기에서는, 장기걸쳐 효과가 있어, 꽤 가독성이 있는 솔루션을 소개합니다(핵심 논리는, 이하의 3 행에 기재되어 있습니다).format★★★★★★★★★★★★★★★★★★」

용용다다 it를 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;
}

테스트 코드

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);
  }
}

알아, 이건 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));

}

출력:

1000 => 1k
5821 => 5.8k
10500 => 10k
101800 => 101k
2000000 => 2m
7800000 => 7.8m
92150000 => 92m
123200000 => 123m
9999999 => 9.9m

다음은 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;
}

출력:

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

math!필!! ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★!
접미사를 문자열이나 배열에 넣고 파워에 따라 가져올 수 있습니다.
전력에 관해서도 사업부를 관리할 수 있지만, 거의 모든 것이 전력의 가치에 관한 것이라고 생각합니다.도움이 됐으면 좋겠다!

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;  
}

출력:

999
1.2k
98k

1.1m
11b
712b
34t

Java-12+에서는 를 사용하여 숫자를 포맷할 수 있습니다.작성할 수 있습니다.NumberFormat 번째 as as as first first

NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);

후, 을 「합니다」에 사용합니다.format:

fmt.format(1000)
$5 ==> "1K"

fmt.format(10000000)
$9 ==> "10M"

fmt.format(1000000000)
$11 ==> "1B"

현재의 회답에 관한 문제

  • 현재 솔루션의 대부분은 이러한 접두사 k=103, m=106, b=109, t=10을12 사용합니다.그러나 다양한 소스에 따르면 올바른 접두사는 k=103, M=106, G=109, T=10이다12.
  • 음수에 대한 지원 부족(또는 음수가 지원된다는 것을 증명하는 테스트 부족)
  • 1.1k를 1100으로 변환하는 등 역연산을 지원하지 않음(단, 이는 원래 질문의 범위를 벗어남)

자바 솔루션

이 솔루션( 답변의 확장)은 위의 문제에 대처합니다.

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);
    }
}

그루비 솔루션

이 솔루션은 원래 아래와 같이 그루비로 작성되었습니다.

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)
    }
}

테스트(구루비)

테스트는 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')
        }
    }
}

큰 숫자를 작은 숫자(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]);
}

테스트

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

도움이 되었으면 좋겠다

ICU lib에는 번호에 대한 규칙 기반 포메터가 있으며, 번호 철자 출력 등에 사용할 수 있습니다.ICU를 사용하면 읽기 쉽고 유지보수가 가능한 솔루션이 될 것입니다.

[사용방법]

오른쪽 클래스는 RuleBasedNumber 입니다.형식. 형식 자체는 별도의 파일(또는 문자열 상수, 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);

같은 페이지에 로마자 숫자가 표시되어 있기 때문에, 당신의 경우도 가능할 것이라고 생각합니다.

다음은 재귀가 없는 간단한 구현과 아주 작은 루프입니다.부정적인 숫자지만 음수에서는동작하지 않지만값을 지원합니다 양의 모든 모두 긍정적 지원하는 하지만 잘 안 됩니다.longs최대 에달려에 있다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);
}

출력:

1k1k
5.8k5.8K
10k10,000
101k101k
2m2m
7.8m780m
92m92m
123m123m
9.2e(이것은 9.2e(이것은Long.MAX_VALUE))

또한 간단한 벤치마킹(1000만 개의 랜덤 롱 포맷)도 실시했습니다.이것은 Eliza의 실장보다 상당히 고속이며, assilias의 실장보다 약간 고속입니다.

나:1137.028 ms내꺼:1137.028 밀리초
엘리야의:2664.396 msEliza:2664.396 밀리초
': 1373.473밀리초

중요:캐스팅 대상 응답double하다, will, 패, will, will, will, will 등의 숫자는 실패한다.99999999999999999L.100P99Pdouble는 다음 표준을 사용합니다.

유효 자리수가 최대 15 자리수의 10 진수가 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

이 솔루션은 불필요한 숫자를 제거하고 모든 값에 대해 작동합니다.심플하지만 퍼포먼스가 뛰어난 실장(아래 비교).-12k는 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];
    }
}

else if입니다. 맨 처음은 최소가 필요하기 때문입니다. 왜냐하면 최소는-(2^63)은 '''입니다.(2^63)-1에, 은 「」입니다.number = -numbernumber == 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;
    }

}

가능한 출력: " " "2309 vs. 11591순서를 로 하는 수집과 수

라운딩하고 싶은 분들을 위해서요.이 솔루션은 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);
        }
    }

다음 코드는 간단한 확장을 염두에 두고 이를 수행하는 방법을 보여 줍니다.

'마법makeDecimal올바른 값으로 전달되는 함수에 대해 출력에 4자를 초과할 수 없습니다.

의 1 부분을 10분의 1을 뽑습니다. 예를 들어 다음과 같습니다.12,345,678로는 을isis with with with with with1,000,000 주다whole의 의 값12 a. a. a.tenths의 의 값3.

여기서 다음 규칙을 사용하여 전체 부분만 출력할지 전체 및 10분의 1 부분 모두를 출력할지를 결정할 수 있습니다.

  • 10분의 1 부분이 0인 경우 전체 부분과 접미사를 출력합니다.
  • 전체 부분이 9보다 크면 전체 부분과 접미사를 출력합니다.
  • 그렇지 않으면 전체 부분, 10분의 1 부분 및 접미사를 출력합니다.

그 코드는 다음과 같습니다.

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);
}

그 후, 도우미 기능을 올바른 값으로 호출하는 것은 간단한 문제이며, 여기에는 개발자의 생활을 보다 쉽게 하기 위한 상수도 포함됩니다.

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");
}

★★★★★★★★★★★★★★★가makeDecimal그르렁거리는 기능이 기능하는 것은 그 이상으로 확장되는 것을 의미합니다.999,999,999에 행을 추가하는 것만으로 끝납니다.Xlat너무 쉬워서 널 위해 해줬지

★★★★★★returnXlat64비트 서명된 긴 길이에서 보유할 수 있는 최대값은 약 9.2조 달러에 불과하기 때문에 조건부여가 필요하지 않습니다.

, 어떤 기이한 Oracle을 128비트 Oracle을 추가합니다.longer "1024"damn_long를 입력하면 준비가 됩니다 :- ) , type :-)


마지막으로 기능 검증에 사용할 수 있는 작은 테스트 하니스입니다.

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));
    }
}

출력으로부터 필요한 것을 얻을 수 있는 것을 알 수 있습니다.

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

이 그 .이 함수는 다음에 이어지기 때문입니다.< THOU질문에서 음이 아닌 값만 언급하셨기 때문에 괜찮다고 생각했습니다.

이게 최선의 방법인지는 모르겠지만, 저는 이렇게 했습니다.

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

--- 코드---

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
}

이건 내 암호야깔끔하고 소박하다

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];

}

자바는 녹슬었지만, 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");
    }

미터 킬로가 아닌 CS 킬로(1,024)를 사용하거나 단위를 추가하는 것은 간단합니다.1,000을 "1k"가 아닌 "1.0k"로 포맷하지만, 그건 중요하지 않다고 생각합니다.

보다 구체적인 요건인 「4 문자 이내」를 만족시키려면 , 접미사 앞의 스페이스를 삭제하고, 중간 블록을 다음과 같이 조정합니다.

if (value >= unit)
  {
  value /= unit;
  return (value).ToString(value >= unit * 9.95 ? "#,##0" : "#,##0.0") + suffixes[--j];
  }

내가 제일 좋아하는.전자 도메인에서 흔히 볼 수 있듯이 "k" 등을 10진수 표시기로 사용할 수도 있습니다.그러면 추가 공간 없이 추가 숫자가 제공됩니다.

두 번째 열은 가능한 한 많은 숫자를 사용하려고 합니다.

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

이것이 코드입니다.

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?";
}
}

제일이 있는지 하게 알 수 (사용자가합니다).BigDecimal퍼포먼스에 대해 걱정할 필요 없이 (자체 기록 코드를 신뢰합니다) 과도한 코멘트를 하지 않아도 됩니다(성능이 고려 대상이 될 정도로 몇 백만 번을 원하는 시나리오를 상상할 수 없기 때문입니다).

이 버전:

  • BigDecimal의 및 반올림 : " " " " " " " " " "
  • OP의 요청에 따라 반올림 작업
  • 는, 모드( 른른합니다.HALF_UP
  • 할 수 할 수 있습니다).REQUIRED_PRECISION)
  • 는 을 합니다.enum하려면 , k KB 를 하도록 간단하게 할 수 있습니다.또, 물론, k/m/b/t 를 도 가능합니다TRILLION
  • 철저한 단위 테스트가 수반됩니다. 문제의 테스트 케이스는 경계를 테스트하지 않았기 때문입니다
  • 0과 음수에 대해 작동해야 합니다.

Threshold.java:

import java.math.BigDecimal;

public enum Threshold {
  TRILLION("1000000000000", 12, 't', null),
  BILLION("1000000000", 9, 'b', TRILLION),
  MILLION("1000000", 6, 'm', BILLION),
  THOUSAND("1000", 3, 'k', MILLION),
  ZERO("0", 0, null, THOUSAND);

  private BigDecimal value;
  private int zeroes;
  protected Character suffix;
  private Threshold higherThreshold;

  private Threshold(String aValueString, int aNumberOfZeroes, Character aSuffix,
      Threshold aThreshold) {
    value = new BigDecimal(aValueString);
    zeroes = aNumberOfZeroes;
    suffix = aSuffix;
    higherThreshold = aThreshold;
  }

  public static Threshold thresholdFor(long aValue) {
    return thresholdFor(new BigDecimal(aValue));
  }

  public static Threshold thresholdFor(BigDecimal aValue) {
    for (Threshold eachThreshold : Threshold.values()) {
      if (eachThreshold.value.compareTo(aValue) <= 0) {
        return eachThreshold;
      }
    }
    return TRILLION; // shouldn't be needed, but you might have to extend the enum
  }

  public int getNumberOfZeroes() {
    return zeroes;
  }

  public String getSuffix() {
    return suffix == null ? "" : "" + suffix;
  }

  public Threshold getHigherThreshold() {
    return higherThreshold;
  }
}

Number Shortener.java:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class NumberShortener {

  public static final int REQUIRED_PRECISION = 2;

  public static BigDecimal toPrecisionWithoutLoss(BigDecimal aBigDecimal,
      int aPrecision, RoundingMode aMode) {
    int previousScale = aBigDecimal.scale();
    int previousPrecision = aBigDecimal.precision();
    int newPrecision = Math.max(previousPrecision - previousScale, aPrecision);
    return aBigDecimal.setScale(previousScale + newPrecision - previousPrecision,
        aMode);
  }

  private static BigDecimal scaledNumber(BigDecimal aNumber, RoundingMode aMode) {
    Threshold threshold = Threshold.thresholdFor(aNumber);
    BigDecimal adjustedNumber = aNumber.movePointLeft(threshold.getNumberOfZeroes());
    BigDecimal scaledNumber = toPrecisionWithoutLoss(adjustedNumber, REQUIRED_PRECISION,
        aMode).stripTrailingZeros();
    // System.out.println("Number: <" + aNumber + ">, adjusted: <" + adjustedNumber
    // + ">, rounded: <" + scaledNumber + ">");
    return scaledNumber;
  }

  public static String shortenedNumber(long aNumber, RoundingMode aMode) {
    boolean isNegative = aNumber < 0;
    BigDecimal numberAsBigDecimal = new BigDecimal(isNegative ? -aNumber : aNumber);
    Threshold threshold = Threshold.thresholdFor(numberAsBigDecimal);
    BigDecimal scaledNumber = aNumber == 0 ? numberAsBigDecimal : scaledNumber(
        numberAsBigDecimal, aMode);
    if (scaledNumber.compareTo(new BigDecimal("1000")) >= 0) {
      scaledNumber = scaledNumber(scaledNumber, aMode);
      threshold = threshold.getHigherThreshold();
    }
    String sign = isNegative ? "-" : "";
    String printNumber = sign + scaledNumber.stripTrailingZeros().toPlainString()
        + threshold.getSuffix();
    // System.out.println("Number: <" + sign + numberAsBigDecimal + ">, rounded: <"
    // + sign + scaledNumber + ">, print: <" + printNumber + ">");
    return printNumber;
  }
}

(「」의 코멘트를 해제합니다.println스테이트먼트 또는 변경을 실시해, 마음에 드는 로거를 사용해 동작을 확인합니다).

그리고 마지막으로, Number의 테스트는쇼터테스트(일반 JUnit 4):

import static org.junit.Assert.*;

import java.math.BigDecimal;
import java.math.RoundingMode;

import org.junit.Test;

public class NumberShortenerTest {

  private static final long[] NUMBERS_FROM_OP = new long[] { 1000, 5821, 10500, 101800, 2000000, 7800000, 92150000, 123200000 };
  private static final String[] EXPECTED_FROM_OP = new String[] { "1k", "5.8k", "10k", "101k", "2m", "7.8m", "92m", "123m" };
  private static final String[] EXPECTED_FROM_OP_HALF_UP = new String[] { "1k", "5.8k", "11k", "102k", "2m", "7.8m", "92m", "123m" };
  private static final long[] NUMBERS_TO_TEST = new long[] { 1, 500, 999, 1000, 1001, 1009, 1049, 1050, 1099, 1100, 12345, 123456, 999999, 1000000,
      1000099, 1000999, 1009999, 1099999, 1100000, 1234567, 999999999, 1000000000, 9123456789L, 123456789123L };
  private static final String[] EXPECTED_FROM_TEST = new String[] { "1", "500", "999", "1k", "1k", "1k", "1k", "1k", "1k", "1.1k", "12k", "123k",
      "999k", "1m", "1m", "1m", "1m", "1m", "1.1m", "1.2m", "999m", "1b", "9.1b", "123b" };
  private static final String[] EXPECTED_FROM_TEST_HALF_UP = new String[] { "1", "500", "999", "1k", "1k", "1k", "1k", "1.1k", "1.1k", "1.1k", "12k",
      "123k", "1m", "1m", "1m", "1m", "1m", "1.1m", "1.1m", "1.2m", "1b", "1b", "9.1b", "123b" };

  @Test
  public void testThresholdFor() {
    assertEquals(Threshold.ZERO, Threshold.thresholdFor(1));
    assertEquals(Threshold.ZERO, Threshold.thresholdFor(999));
    assertEquals(Threshold.THOUSAND, Threshold.thresholdFor(1000));
    assertEquals(Threshold.THOUSAND, Threshold.thresholdFor(1234));
    assertEquals(Threshold.THOUSAND, Threshold.thresholdFor(9999));
    assertEquals(Threshold.THOUSAND, Threshold.thresholdFor(999999));
    assertEquals(Threshold.MILLION, Threshold.thresholdFor(1000000));
  }

  @Test
  public void testToPrecision() {
    RoundingMode mode = RoundingMode.DOWN;
    assertEquals(new BigDecimal("1"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 1, mode));
    assertEquals(new BigDecimal("1.2"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 2, mode));
    assertEquals(new BigDecimal("1.23"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 3, mode));
    assertEquals(new BigDecimal("1.234"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 4, mode));
    assertEquals(new BigDecimal("999").toPlainString(), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("999"), 4, mode).stripTrailingZeros()
        .toPlainString());
    assertEquals(new BigDecimal("999").toPlainString(), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("999"), 2, mode).stripTrailingZeros()
        .toPlainString());
    assertEquals(new BigDecimal("999").toPlainString(), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("999.9"), 2, mode).stripTrailingZeros()
        .toPlainString());

    mode = RoundingMode.HALF_UP;
    assertEquals(new BigDecimal("1"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 1, mode));
    assertEquals(new BigDecimal("1.2"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 2, mode));
    assertEquals(new BigDecimal("1.23"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 3, mode));
    assertEquals(new BigDecimal("1.235"), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("1.23456"), 4, mode));
    assertEquals(new BigDecimal("999").toPlainString(), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("999"), 4, mode).stripTrailingZeros()
        .toPlainString());
    assertEquals(new BigDecimal("999").toPlainString(), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("999"), 2, mode).stripTrailingZeros()
        .toPlainString());
    assertEquals(new BigDecimal("1000").toPlainString(), NumberShortener.toPrecisionWithoutLoss(new BigDecimal("999.9"), 2, mode)
        .stripTrailingZeros().toPlainString());
  }

  @Test
  public void testNumbersFromOP() {
    for (int i = 0; i < NUMBERS_FROM_OP.length; i++) {
      assertEquals("Index " + i + ": " + NUMBERS_FROM_OP[i], EXPECTED_FROM_OP[i],
          NumberShortener.shortenedNumber(NUMBERS_FROM_OP[i], RoundingMode.DOWN));
      assertEquals("Index " + i + ": " + NUMBERS_FROM_OP[i], EXPECTED_FROM_OP_HALF_UP[i],
          NumberShortener.shortenedNumber(NUMBERS_FROM_OP[i], RoundingMode.HALF_UP));
    }
  }

  @Test
  public void testBorders() {
    assertEquals("Zero: " + 0, "0", NumberShortener.shortenedNumber(0, RoundingMode.DOWN));
    assertEquals("Zero: " + 0, "0", NumberShortener.shortenedNumber(0, RoundingMode.HALF_UP));
    for (int i = 0; i < NUMBERS_TO_TEST.length; i++) {
      assertEquals("Index " + i + ": " + NUMBERS_TO_TEST[i], EXPECTED_FROM_TEST[i],
          NumberShortener.shortenedNumber(NUMBERS_TO_TEST[i], RoundingMode.DOWN));
      assertEquals("Index " + i + ": " + NUMBERS_TO_TEST[i], EXPECTED_FROM_TEST_HALF_UP[i],
          NumberShortener.shortenedNumber(NUMBERS_TO_TEST[i], RoundingMode.HALF_UP));
    }
  }

  @Test
  public void testNegativeBorders() {
    for (int i = 0; i < NUMBERS_TO_TEST.length; i++) {
      assertEquals("Index " + i + ": -" + NUMBERS_TO_TEST[i], "-" + EXPECTED_FROM_TEST[i],
          NumberShortener.shortenedNumber(-NUMBERS_TO_TEST[i], RoundingMode.DOWN));
      assertEquals("Index " + i + ": -" + NUMBERS_TO_TEST[i], "-" + EXPECTED_FROM_TEST_HALF_UP[i],
          NumberShortener.shortenedNumber(-NUMBERS_TO_TEST[i], RoundingMode.HALF_UP));
    }
  }
}

중요한 테스트 케이스를 놓쳤거나 기대치를 조정해야 할 경우 언제든지 코멘트로 지적해 주십시오.

나만의 답변, 자바 코드, 자체 설명 코드 추가..

import java.math.BigDecimal;

/**
 * Method to convert number to formatted number.
 * 
 * @author Gautham PJ
 */
public class ShortFormatNumbers
{

    /**
     * Main method. Execution starts here.
     */
    public static void main(String[] args)
    {

        // The numbers that are being converted.
        int[] numbers = {999, 1400, 2500, 45673463, 983456, 234234567};


        // Call the "formatNumber" method on individual numbers to format 
        // the number.
        for(int number : numbers)
        {
            System.out.println(number + ": " + formatNumber(number));
        }

    }


    /**
     * Format the number to display it in short format.
     * 
     * The number is divided by 1000 to find which denomination to be added 
     * to the number. Dividing the number will give the smallest possible 
     * value with the denomination.
     * 
     * @param the number that needs to be converted to short hand notation.
     * @return the converted short hand notation for the number.
     */
    private static String formatNumber(double number)
    {
        String[] denominations = {"", "k", "m", "b", "t"};
        int denominationIndex = 0;

        // If number is greater than 1000, divide the number by 1000 and 
        // increment the index for the denomination.
        while(number > 1000.0)
        {
            denominationIndex++;
            number = number / 1000.0;
        }

        // To round it to 2 digits.
        BigDecimal bigDecimal = new BigDecimal(number);
        bigDecimal = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_EVEN);


        // Add the number with the denomination to get the final value.
        String formattedNumber = bigDecimal + denominations[denominationIndex];
        return formattedNumber;
    }

}
//code longer but work sure...

public static String formatK(int number) {
    if (number < 999) {
        return String.valueOf(number);
    }

    if (number < 9999) {
        String strNumber = String.valueOf(number);
        String str1 = strNumber.substring(0, 1);
        String str2 = strNumber.substring(1, 2);
        if (str2.equals("0")) {
            return str1 + "k";
        } else {
            return str1 + "." + str2 + "k";
        }
    }

    if (number < 99999) {
        String strNumber = String.valueOf(number);
        String str1 = strNumber.substring(0, 2);
        return str1 + "k";
    }

    if (number < 999999) {
        String strNumber = String.valueOf(number);
        String str1 = strNumber.substring(0, 3);
        return str1 + "k";
    }

    if (number < 9999999) {
        String strNumber = String.valueOf(number);
        String str1 = strNumber.substring(0, 1);
        String str2 = strNumber.substring(1, 2);
        if (str2.equals("0")) {
            return str1 + "m";
        } else {
            return str1 + "." + str2 + "m";
        }
    }

    if (number < 99999999) {
        String strNumber = String.valueOf(number);
        String str1 = strNumber.substring(0, 2);
        return str1 + "m";
    }

    if (number < 999999999) {
        String strNumber = String.valueOf(number);
        String str1 = strNumber.substring(0, 3);
        return str1 + "m";
    }

    NumberFormat formatterHasDigi = new DecimalFormat("###,###,###");
    return formatterHasDigi.format(number);
}

이 코드는 매우 단순하고 깨끗한 코드이며, 완전히 작동합니다.

private static char[] c = new char[]{'K', 'M', 'B', 'T'};
private String formatK(double n, int iteration) {
    if (n < 1000) {
        // print 999 or 999K
        if (iteration <= 0) {
            return String.valueOf((long) n);
        } else {
            return String.format("%d%s", Math.round(n), c[iteration-1]);
        }
    } else if (n < 10000) {
        // Print 9.9K
        return String.format("%.1f%s", n/1000, c[iteration]);
    } else {
        // Increase 1 iteration
        return formatK(Math.round(n/1000), iteration+1);
    }
}

다음을 수행합니다.

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
}

Maven Central에 해결책이 있습니다.

<dependency>
  <groupId>com.github.bogdanovmn.humanreadablevalues</groupId>
  <artifactId>human-readable-values</artifactId>
  <version>1.0.1</version>
</dependency>

바이트 또는 초 단위로 값을 얻을 수 있습니다.또한 자체 인수분해 클래스를 만들 수도 있습니다.

문서 https://github.com/bogdanovmn/java-human-readable-values

초의 예

assertEquals(
    "2h 46m 40s",
    new SecondsValue(10000).fullString()
);

assertEquals(
    "2.8h",
    new SecondsValue(10000).shortString()
);

바이트의 예

assertEquals(
    "9K 784b",
    new BytesValue(10000).fullString()
);

assertEquals(
    "9.8K",
    new BytesValue(10000).shortString()
);

입력 번호(1000, 100000, 1000000, 1000000000 등)에 따라 제수를 설정합니다.

크기가 1이면 숫자의 전체 부분(분수가 없는 첫 번째 부분)을 확인하고 긴 + 문자열로 입력합니다. 크기가 > = 2이면 입력을 나누고 DecimalFormat을 사용하여 원하는 대로 소수 부분을 표시합니다.

//.setRoundingMode(RoundingMode)를 사용할 수 있습니다.DOWN) 반올림 처리

public static String format(long num) {

        String suffix = "", result;
        double divisor = 0;

        DecimalFormat df = new DecimalFormat("##");
        DecimalFormat ds = new DecimalFormat("##.#");
        // ds.setRoundingMode(RoundingMode.DOWN);

        if ( num >= 1000  && num < 1000000 ) {
            divisor = 1000;
            suffix = "K";
        } else if ( num >= 1000000 && num < 1000000000 ) {
            divisor = 1000000;
            suffix = "M";
        } else if (num >= 1000000000) {
            divisor = 1000000000;
            suffix = "B";
        } else {
            System.out.print("The number is Too big > T or TOO small < K");
        }

        int numlengt = df.format(num / divisor).length();

        if (numlengt >= 2) {
            result = (long) (num / divisor) + suffix;
        } else {
            result = ds.format(num / divisor) + suffix;
        }
        return result;
    }
public class NumberToReadableWordFormat {

    public static void main(String[] args) {
        Integer[] numbers = new Integer[]{1000, 5821, 10500, 101800, 2000000, 7800000, 92150000, 123200000, 9999999,999};
        for(int n : numbers) {
            System.out.println(n + " => " + coolFormat(n));
        }
    }

    private static String[] c = new String[]{"K", "L", "Cr"};
    private static String coolFormat(int n) {
        int size = String.valueOf(n).length();
        if (size>=4 && size<6) {
                int value = (int) Math.pow(10, 1);
                double d = (double) Math.round(n/1000.0 * value) / value;
                return (double) Math.round(n/1000.0 * value) / value+" "+c[0];
        } else if(size>5 && size<8) {
                int value = (int) Math.pow(10, 1);
                return (double) Math.round(n/100000.0 * value) / value+" "+c[1];
        } else if(size>=8) {
                int value = (int) Math.pow(10, 1);
                return (double) Math.round(n/10000000.0 * value) / value+" "+c[2];
        } else {
            return n+"";
        }
    }
}

출력:

1000 => 1.0 K

5821 => 5.8 K

10500 => 10.5 K

101800 => 1.0 L

2000000 => 20.0 L

7800000 => 78.0 L

92150000 => 9.2 Cr

123200000 => 12.3 Cr

9999999 => 100.0 L

999 => 999

여기 당신의 문제에 대한 또 다른 간단한 해결책이 있습니다.말하게 하다

String abbr="M,K,T,B";

double yvalue=일부 난수, 문자열 ="#.##" //원하는 장소 선택 가능

public  String format(Double yvalue, String string,String abbr) {
    DecimalFormat df = new DecimalFormat(getnumberformatpattern(string));
      if (yvalue < 0) return "-" + format(-yvalue,string,abbr);
          double finalvalue= yvalue;
          String newnumber="";
          
                if (abbr.indexOf("K")>0){   
                    finalvalue= (yvalue / 1e3);
                    newnumber=df.format(finalvalue) +'K';
                }
                if (abbr.indexOf("M")>0 ){
                if(yvalue>=1e6){
                    finalvalue= (yvalue / 1e6);
                    newnumber=df.format(finalvalue) +'M';
                    };
                }
                if (abbr.indexOf("B")>0 )
                {
                if((newnumber.indexOf("M")<0) || yvalue>=1e9){
                    finalvalue= (yvalue / 1e9);
                    newnumber=df.format(finalvalue) +'B';                   }
                }
                if (abbr.indexOf("T")>0 ){ 
                if((newnumber.indexOf("B")<0) || yvalue>=1e12){
                    finalvalue= (yvalue / 1e12);
                    newnumber=df.format(finalvalue) +'T';                   }
                }
                return newnumber;
    }
  fun getKLCrValue(input: Long):String{
        return if(input.toString().length<4){
            input.toString()
        }else if(input.toString().length<5)
            ( ""+getExactValue(input.toString()[0] +"."+ input.toString()[1]) +"K")
        else if(input.toString().length<6)
            (""+getExactValue(""+input.toString().subSequence(0, 2) +"."+ input.toString()[2]) +"K")
        else if(input.toString().length<7)
            (""+ getExactValue( input.toString()[0] +"."+input.toString().subSequence(1, 3))+"L")
        else if(input.toString().length<8)
            (""+ getExactValue( ""+input.toString().subSequence(0, 2)+"."+input.toString().subSequence(2,4))+"L")
        else if(input.toString().length<9)
            (""+ getExactValue( input.toString()[0] +"."+input.toString().subSequence(1,3))+"Cr")
        else
            (""+ getExactValue( ""+input.toString().subSequence(0, input.toString().length-7)+"."+input.toString().subSequence( input.toString().length-7, input.toString().length-5))+"cr")

    }

    private fun getExactValue(value: String): String {
        return value.replace(".00", "")
    }

getKLCrValue(1234)에 전화하면 원하는 출력을 얻을 수 있습니다.

출력-->

1 -> 1
10 -> 10
12 -> 12
100 -> 100
123 -> 123
1000 -> 1K
1234 -> 1.2K
10000 -> 10K
12345 -> 12.3K
100000 -> 1L
123456 -> 1.23L
1000000 -> 10L
1234567 -> 12.34L
10000000 -> 1cr
12345678 -> 1.23cr
100000000 -> 10cr
123456789 -> 12.34cr
1000000000 -> 100cr
1234567890 -> 123.45cr
10000000000 -> 1000cr
11111111111 -> 1111.11cr

언급URL : https://stackoverflow.com/questions/4753251/how-to-go-about-formatting-1200-to-1-2k-in-java

반응형