Displaying a letter grade based on a percentage Here is a class I made that is able to ask a teacher what percentage their student has in a class and gives them back a grade. The code is very repetitive and I am wondering what I can do to simplify the class below before inputting any more grades.

import java.util.Scanner;

public class Grades{
    public static void main(String [] args){
        Scanner grades = new Scanner(System.in);

        int x = 0;

        System.out.print("What is the percentage of the student: ");
        x = grades.nextInt();

        if (x &gt; 100 || x &lt; 0){
                System.out.println("Please put in a percent from 0 - 100!\n");
        }

        while (x &gt; 100 || x &lt; 0 ){

            System.out.print("What is the percentage of the student: ");
            x = grades.nextInt();
            if (x &gt; 100 || x &lt; 0){
                System.out.println("Please put in a percent from 0 - 100!\n");
            }
        }
        if (x &lt;= 100 &amp;&amp; x &gt;= 96){
             System.out.print("A+");
        }
         if (x &lt;= 95 &amp;&amp; x &gt;= 92){
             System.out.print("A");
        }
         if (x &lt;= 91 &amp;&amp; x &gt;= 90){
             System.out.print("A-");
        }
         if (x &lt;= 89 &amp;&amp; x &gt;= 50){
             System.out.print("B+");
        }
         if (x &lt;= 49 &amp;&amp; x &gt;= 0){
             System.out.print("B");
        }
        // so on and so forth down the grading scale
    }
}
It would be good to split the different sub-tasks to different functions,
for example:


int promptScore(): a method to prompt for score
String getGrade(int score): a method to return the grade from the score


The promptScore method could use an infinite loop with two steps:


Ask for a number
If the number is within the range, return it


The getGrade method could use a sorted map that stores the limits and the corresponding grades.
You could iterate over the entries in this map,
and when you find a value that is below the limit, then you return the corresponding grade.

Something like this:

class Grades {

    private static final Map&lt;Integer, String&gt; limits;

    static {
        limits = new TreeMap&lt;&gt;();
        limits.put(50, "B");
        limits.put(90, "B+");
        limits.put(92, "A-");
        limits.put(96, "A");
        limits.put(101, "A+");
    }

    public static int promptScore() {
        Scanner scanner = new Scanner(System.in);

        while (true) {
            System.out.print("What is the percentage of the student: ");
            int x = scanner.nextInt();

            if (0 &lt;= x &amp;&amp; x &lt;= 100) {
                return x;
            }
            System.out.println("Please put in a percent from 0 - 100!\n");
        }
    }

    public static String getGrade(int score) {
        for (Map.Entry&lt;Integer, String&gt; entry : limits.entrySet()) {
            int limit = entry.getKey();
            if (score &lt; limit) {
                return entry.getValue();
            }
        }
        throw new AssertionError("Impossible case");
    }

    public static void main(String[] args) {
        System.out.println(getGrade(promptScore()));
    }
}


The benefit of splitting up the functions like this is that writing unit tests becomes easy:

@Test
public void testB() {
    assertEquals("B", Grades.getGrade(0));
    assertEquals("B", Grades.getGrade(49));
}

@Test
public void testB_Plus() {
    assertEquals("B+", Grades.getGrade(50));
    assertEquals("B+", Grades.getGrade(89));
}

@Test
public void testA_Minus() {
    assertEquals("A-", Grades.getGrade(90));
    assertEquals("A-", Grades.getGrade(91));
}

@Test
public void testA() {
    assertEquals("A", Grades.getGrade(92));
    assertEquals("A", Grades.getGrade(95));
}

@Test
public void testA_Plus() {
    assertEquals("A+", Grades.getGrade(96));
    assertEquals("A+", Grades.getGrade(100));
}