This week's book giveaway is in the OCPJP forum. We're giving away four copies of OCA/OCP Java SE 7 Programmer I & II Study Guide and have Kathy Sierra & Bert Bates on-line! See this thread for details.

I wrote the above logic in my project to calculate Grade according to GPA obtained. Every thing alright but there is a little problem, when I assign the value of grade as 3.3 it never show B+ it always shows B grade.
even if I assign 3.31 to grade it will show B+ but it show B Grade on 3.3.
I wrote the above code in java as well as in c and c++, but got same problem. Can anyone explain why is that?

Hmmm... if "grade" is a double, your code ought to work. If it is a float, you're going to find out something worth knowing about how a lot of computer languages (including Java) represent decimal values internally.

To get a lead on it, try this:
Then try this:
And you'll be surprised.

Something like that would be a good option, Justin. But sonu really needs to understand where his problem originates. While integer math tends mostly to do what you want (not counting overflows and so forth), floating-point math is often a bit perplexing to a new programmer. His problem presents a classic example of what can happen when a programmer mistakes code for algebra. Once he knows why your suggestion is a good idea, your suggestion will be, well... a good idea!

Stevens Miller wrote:Hmmm... if "grade" is a double, your code ought to work. If it is a float, you're going to find out something worth knowing about how a lot of computer languages (including Java) represent decimal values internally.
[/code]

Thank you Stevens. There is one more problem see this:

this the calculation part of my project:

import java.io.*;
import java.util.*;

public class Stud implements Serializable
{
public int i,n=0;;
public String name,roll_no;//student's name and rollno.
public String sub[]=new String[10];//array for subject's name
static Scanner input;
public int c[]=new int[10];//array for credit obtained in that subject
public double g[]=new double[10];//array for gpa obtained in that subject
public double ps[]=new double[10];//array for calculating product of credit and goa in that subject.
public double totalc,totalps,grade;//variables for calculating total credit,total sum of (credit*gpa) and grade.

public void inputR()
{
for(i=0;i<n;i++)
{
input=new Scanner(System.in);

System.out.print("Enter Subject no."+(i+1)+"\t");
sub[i]=input.nextLine();
System.out.print("Enter the credit of the subject : ");
c[i]=input.nextInt();
System.out.print("Enter the GPA obtained in that subject : ");
g[i]=input.nextDouble();

if(g[i]>4.4)//gpa can't exceed 4.3
{
System.out.print("Sorry!!! Wrong input! GPA must be less than 4.3...please re-enter: "); g[i]=input.nextFloat();
}
ps[i]=(g[i]*c[i]);//product of credit and gpa in that subject
}
totalc=0; totalps=0;
for(i=0;i<n;i++)
{
totalc=totalc + c[i];totalps=totalps + ps[i]; //getting total credit and total product sum.
System.out.println();
}

public void line()
{
for(int i=0;i<26;i++)
System.out.print("---");
System.out.println();
System.out.println();
}

}

I got my problem solved in case of subject grade but still having problem in overall grade because :-
when this line compiles: grade=(totalps/totalc);
i.e. grade=(9.9/3); it gives 3.299999999999994 not 3.3 which further gives B as a grade not B+
how to solve this one please help!!

Junilu Lacar wrote:If you must have precision, use BigDecimal

Alas, Junilu, that isn't going to solve sonu's problem. Here's some code that shows why not:

Run this, and you get this output:

From this, you can see a couple of things. First, even the extended precision of a class like BigDecimal doesn't mean you are storing a value like 9.9 exactly. You are simply storing an approximation of 9.9 to quite a number of decimal places. Perhaps accurate enough for things like testing Ohm's Opinion in your home electronics lab, or landing the Curiousity rover on Mars, but not enough to soothe the tortured soul of some graduate student who placed below a colleague because the colleague falsely scored .0000000000000003552713678800500929355621337890625 higher on some grading scale than he or she did.

Now, there are all kinds of ways to store 9.9 exactly, but even those aren't guaranteed to solve sonu's problem. That's because the problem calls for arbitrary arithmetic on totals, with that arithmetic yielding exact results. All computer storage is discrete, meaning that all numbers are, one way or another, scaled integers. That's fine for addition, multiplication, and subtraction, which are closed under the whole numbers. But, once you start to divide things into each other, all Heck breaks lose, as the the results may call for "non-terminating decimal expansion," for which, as the exception thrown above rather nihilistically informs us, there is "no exact representable decimal result." So, "precision" isn't the answer. The answer is a representational form that doesn't require division.

For example, suppose the possible grades in a course are "A+," "A", "A-", "B+", and so on, down to "F." One could assign each of these an integer value, such as A+ = 15, A = 14, and so on, down to F = 2. (Why F = 2 instead of F = 3 I leave as an exercise for the new programmer to figure out. Also, why A+ = 15 and F = 2, as opposed to A+ = 1035 and F = 1022 I also leave as an exercise, though I will leave the hint that A+ = 1035 and F = 1022 will work just fine, as will A+ = 5 and F = -8). To get an average grade, one simply adds the integer values of all the course grades (weighted by credits) into a single sum (what totalp does in sonu's code) and all the course credits into a single sum (what totalc does in sonu's code). But then, one must store these together, never dividing the course-grade sum by the course-credit sum. Instead, one compares the two sums to a scaled range limit expressed as two integers. So, if a student were to take classes of 1, 2, and 3 credits, and score an A-, B, and C in those classes, their overall weighted score would be 13 * 1 + 11 * 2 + 8 * 3 = 59. Their overall credit total would be 1 + 2 + 3 = 6. Their average would then be 59 / 6 = 9.8333... (which you can't represent exactly in a double or even a BigDecimal).

Now, sonu's grading scale is pretty strict: it doesn't round up, so 9.8333... is going to get our student a C+. But, we want to avoid the nasty case where the scale is set exactly at some value that is so close to the student's weighted average that it presents the error sonu found. To do that, we need to represent the scale itself as pairs of integers that we do not divide.

Happily, we have already done that! Each of our letter grades was set to an integer in the first place. But, how do we compare those integers to the student's weighted total? We do it by scaling the letter-grade numbers up to the total number of credits the student has earned. In our example, that's 6 credits. So, the cut-off value for an A+ is 15 * 6 = 90. Our poor student's 59 isn't very close to that. Sliding down into mediocrity, we find that B- = 10 implies a weighted value of 10 * 6 = 60, and that C+ = 9 implies a weighted value of 9 * 6 = 54. Our student's 59 is between those. Because sonu is a harsh grader, we drop down from 59 to the closest value below that, of 54, and our student gets a "C+," a pat on the back, and a reminder that life holds other rewards beyond merely those which you can obtain in the academy.

Note that this solution can be implemented entirely in native types (integers, that is), and that it is exact, with no rounding or approximations (because it never does any division, nor relies on representations of any non-integer values).

The above is (I think) a complete solution to your problem, which is ordinarily something I believe is frowned upon in the Beginner's forum. However, as you can see, it's not quite as easy as falling off a log, and really requires more of an expanded way of thinking about how a computer works to understand, than just translating it into code. (Also, I remember my days as a graduate student, when we were assigned the problem of writing functions to do basic math on values way too big for storage in 32-bit longs. One of my classmates told the professor he couldn't do it, since his compiler's largest native type was a 32-bit long. The professor leeringly told him, "That's the problem." The poor kid had no clue what to do, and the professor had taught a terrible course up to that point, so I--standing nearby where I could overhear--said, "Try using an array to store your digits." The professor looked at me and shouted, "That is cheating!" Yeah, well... he can sue me. There's a lot more to coding arbitrary-precision math functions than saying, "Try using an array to store your digits," and if the professor hadn't done enough to give his student a chance at solving the problem, that's not my fault. Consider this my final payback to that smug SOB.)

Anyway, the short answer is: think of a way to represent your scores, credits, totals, and grading scales all strictly in integers.