1

I am wondering if it's possible to number format a BigInteger in Java by converting to 2 decimal places and adding a Suffix?

E.g 1000 = 1.00k, 1000000000000 = 1.00t

I am currently using the following code which is perfect for formatting longs...

public static String withSuffix (long count) {
    if (count < 1000) return "" + count;
    int exp = (int) (Math.log(count) / Math.log(1000));
    return String.format("%.2f %c", count / Math.pow(1000, exp), "kMBTab".charAt(exp-1));
}

Is there a way to do something like this, but for BigIntegers?

Thanks in advance!

Adam
  • 9
  • 3
  • 1
    https://stackoverflow.com/questions/6827516/logarithm-for-biginteger gives examples of how to compute `log()` for `BigInteger`. You have the rest. – Roman Puchkovskiy Mar 19 '18 at 18:28
  • Absolute legend, thank you so much!! – Adam Mar 19 '18 at 18:44
  • Okay here is the another question https://stackoverflow.com/questions/4753251/how-to-go-about-formatting-1200-to-1-2k-in-java you can implement suitable answer from this or take it as a reference. – Modi Harsh Sep 12 '20 at 19:39

2 Answers2

0

Here is an example of a formatter:

String[] suffixes = { "€", "K", "M", "T"};

public final String format(BigInteger value) {

    // As a string
    String stringValue = value.toString();
    // Packets are groups of three numbers
    final List<String> packets = new ArrayList<>();

    // Create packets
    for (int i = stringValue.length(); 0 < i; i -= 3) {
        if (i <= 3) {
        packets.add(0, stringValue);
        break;
        }
        packets.add(0, stringValue.substring(i - 3));
        stringValue = stringValue.substring(0, i - 3);
    }

    // Create the number according to its length
    final StringBuilder sb = new StringBuilder();
    if (packets.size() > 1) {
        sb.append(packets.get(0));
        sb.append(".");
        sb.append(packets.get(1).substring(0, 2));
        sb.append(suffixes[packets.size()]);
    } else {
        System.out.println(packets.get(0) + "€");
        return packets.get(0) + "€";
    }
    System.out.println(sb.toString());
    return sb.toString();
}

It formats a BigInteger to a String like 547.58T or 0€. The only issue is that it doesn't support negative numbers so well.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
0

Fortunately, there is a solution on the Maven Central.

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

You can just get values for amount of bytes or seconds. Also you can create you own fraction class.

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

Seconds example

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

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

Bytes example

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

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

Customization example

public class MyTypeValue extends FractionatedValue {
    public MyTypeValue(long value) {
        super(
            value,
            new FractionSpecification(
                FractionDefinition.builder()
                    .name("the minimal fraction unit")
                    .shortNotation("foo")
                    .minimalUnitsAmount(1)
                .build(),

                FractionDefinition.builder()
                    .name("another fraction unit")
                    .shortNotation("baz")
                    .minimalUnitsAmount(60)
                .build(),

                FractionDefinition.builder()
                    .name("the last fraction unit")
                    .shortNotation("foo baz")
                    .minimalUnitsAmount(3600)
                .build()
            )
        );
    }
}

...

assertEquals(
    "2foo 46baz 40foo baz",
    new MyTypeValue(10000).fullString()
);
Elegant.Obj
  • 131
  • 1
  • 12