How can I loop based on remainders, percentages, or floating point values?

88 Views Asked by At

My assignment asks me to take a data set in the form of different integers, and run them through a method that will print the appropriate number of characters to create a horizontal bar graph. The graph needs to use a string made of Block Elements (, , ). The blocks are base 8, so inputting 8 as in integer should print and 16 should print ██.

I figured out a way to print the right number of blocks for inputs that are evenly divisible by 8, but I'm not sure how I can work with the remainders or decimal values from uneven division e.g., if (9 / 8) = 1.125, how can I use the 0.125?

This is what I have so far. It prints the appropriate number of characters for multiples of 8.

public static String getHorizontal(int value) {
   String bar = "";
   double realMath = (double) value / 8; // (1/8) = (0.125) (8/8) = 1
   int rmConversion;

   while (realMath % 1 == 0) {
       rmConversion = (int) realMath;
       for (int i = 0; i < rmConversion; i++) {
           bar += "█";
       }
       return bar;
   }

   // TODO: replace this with code that actually generates the bar graph!

   return bar;
}

How can I run a similar loop but with a remainder or decimal point value?

2

There are 2 best solutions below

0
Old Dog Programmer On

Here is one way. Note that all the calculcations in this answers are done in integer arithmetic. No floating point is used.

  • Calculate the number of full blocks that will be needed by dividing by 8.
  • Add 1 to that number to reserve a space for a partial block.
  • Create an array of length determined in the previous step filled with full block characters.
  • Use the % operator to calculate the remainder, which will give the size of a partial block.
  • Replace the last character in the filled array with a space or a partial block, as determined by the result of the remainder calculation.
  • If you really need an explicit loop, replace the Arrays.fill call with your loop.
public static String bar (int value) {
    final char FULL_BLOCK = '█';
    char [] partBlock = {' ','▏','▎','▍','▌','▋','▊','▉' };
    char [] theBar = new char [value / 8 + 1];
    Arrays.fill (theBar, FULL_BLOCK);
    theBar [theBar.length - 1] = partBlock [value % 8];
    return new String (theBar);
}
   
public static void main(String[] args) {
    System.out.println ("Growing Bar:");
    for (int i = 0; i <= 24; ++i) {
        System.out.println (bar (i));
    }
}

Test:

Growing Bar:
 
▏
▎
▍
▌
▋
▊
▉
█ 
█▏
█▎
█▍
█▌
█▋
█▊
█▉
██ 
██▏
██▎
██▍
██▌
██▋
██▊
██▉
███

The uneven height between the full block and the partial blocks seem to be a result of the font Stack Overflow is using. I do not see that difference in the test result anywhere else, such as my IDE, email, or a text editor.

An alternative to using partBlock array is to take advantage of the fact that the partial blocks are consecutive characters in Unicode:

int r = value % 8;
theBar[theBar.length - 1] = r == 0 ? SPACE : (char) ('\u2590' - r);

Of course, the space character doesn't fit in that pattern, so a check has to be done for that.

2
Reilas On

Divide by 8, and round the value to the nearest 0.125.

x = Math.round(x / 8 / .125) * .125

Then, determine which eighths block to use.

x -= Math.floor(x);
char c = (char) (0x258f - (x / .125));

Here is an example.

String getHorizontal(double x) {
    x = Math.round(x / 8 / .125) * .125;
    String s = "\u2588".repeat((int) Math.floor(x));
    x -= Math.floor(x);
    return s + (char) (0x258f - (x / .125));
}

Here is an output.
You'll need a different font, it works with Source Code Pro.

1.125 ▎
11.25 █▌
56.25 ███████▏
112.5 ██████████████▎