Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pretty number formatting algorithm

Tags:

java

algorithm

Algorithm to convert an integer representing a number of bytes into an pretty format. 3 digits max (not counting decimal) - for eg like linux command line. no leading or trailing zeroes 1K is 1000 bytes

Examples:
Correct
123B -> 123B
12300B -> 12.3K
1910000B -> 1.91M
1000000000B -> 1G
83123 = 83.1K (not 83K)

Incorrect
012K (should be 12K)
8.20M (should be 8.2M)

I would like to know what did I do wrong or is there an easy better way to solve this problem or if there are any bugs in my code.

Below is my solution (it works but I was not selected so I have not idea of what I did wrong) -

/*
   * @Description - Function takes integer as input and returns the number in
   * pretty format(Gigabyte, Megabytes, KiloBytes, Bytes) with maximum of 3
   * digits
   * @param integer to convert to pretty format
   * @Assumptions - As mentioned in the problem set, 1000bytes = 1KB
   * Value is rounded to the nearest valid value
   * In java leading 0 in number is considered Octal, this function does not 
   * take care of octal to decimal conversion
   * As 1G = 1,000,000,000B the loop will run maximum 3 times in worst case 
   * Its requires constant space O(1) to store the result
   */
  static String fpretty(int num) {

    int count = 0;
    double div_result = (double) num;
    String display = "";

    /*
     * Every time we divide by 1000 count is incremented from B->K->M->G
     * Here two decimal places are preserved for cases like 1.05, 1.11
     * The output result of this loop will have 1,2 or 3 digits with max
     * two decimal places
     */
    while(div_result > 999.5) {
      div_result = div_result / 1000;
      div_result = Math.round(div_result * 100.0) / 100.0;
      count++;
    }

    // Get suffix B, K, M or G
    String measure = getUnit(count);

    // If decimal places is all zeros OR result has 3 digits
    if(div_result % 1 == 0 || div_result >= 100)
      display = (int)div_result + measure;
    // If result has 2 digits
    else if (div_result >= 10) {
      // Then fetch 1 decimal place as we have 2 digits
      div_result = (Math.round(div_result * 10.0) / 10.0);
      // If after rounding decimal places are .0 then truncate zeros 
      // eg. 99.97 rounded to -> 100.0 -> 100
      if(div_result % 1 == 0)
        display = (int)div_result + measure;
      else
        display = div_result + measure;
    }
    else
      display = div_result + measure;

    return display;
  }
like image 889
nmd Avatar asked Aug 15 '26 05:08

nmd


1 Answers

This can be done with much less effort using the DecimalFormat class. Let it do the rounding for you, which can be described in a pattern and choose the way of rounding by RoundingMode. It also takes care of the trailing zeros, which will be simply ignored.

public String pretty(int num) {
    DecimalFormat f = new DecimalFormat("###.##");
    f.setRoundingMode(RoundingMode.HALF_UP);
    double prettyd = num;
    int count = 0;
    while (prettyd >= 1000.0) {
        prettyd /= 1000.0;
        count++;
    }
    return f.format(prettyd) + getUnit(count);
}
like image 145
Steve Benett Avatar answered Aug 16 '26 18:08

Steve Benett



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!