1

so the program I am making is supposed to be able to determine the mean, median and how many "grades" have been put into the program. trying to get the median to display and not having any errors using I guess a popular way of finding the median (google thinks its a good idea of how to find the median). When I put in a number I always get 0.0 until I max out my array (set to 25) and then it becomes 1.0. Still not really doing anything math that its supposed to be doing.

  DecimalFormat df = new DecimalFormat ("#0.0##");
   String textBoxInputStr;
   String gCountStr;
   double boxInput = 0;
   double[]gradeArray = new double[25];
   int gradeCount = 0;
   double mean = 0;
   String meanStr;
   double sum = 0;
   double median = 0;
   String medianStr;
   do {    
      try {
         if(gradeCount < 25) {
             textBoxInputStr = JOptionPane.showInputDialog(this,"Enter Grade","Enter Grade", JOptionPane.PLAIN_MESSAGE);  //makes texbox

             boxInput = Double.parseDouble(textBoxInputStr);                //parses what goes on in the textbox

             gradeArray[gradeCount] = boxInput;                           //puts the parsed data into the array 
             gradeCount++;                                                //is the tracker for how many grades are entered
             gCountStr = Integer.toString(gradeCount);                    //converts the counter to string
             txtGrades.setText(gCountStr);                                //places the newly converted counter into grades box for display
          }
         else      //an error
             {      
            JOptionPane.showInputDialog(this,"You can only input 25 values","Too Much Data", JOptionPane.PLAIN_MESSAGE); 
             }
     //(Above) this is all to keep track of how many grades are entered and all the grades are stored in the array.
     //start of median stuff
     Arrays.sort(gradeArray, 0, gradeCount);
  if (gradeCount % 2 == 0) {
      median = ((double)gradeArray[gradeCount/2] + (double)gradeArray[gradeCount/2 - 1])/2;
     medianStr = Double.toString(median);
      txtMedian.setText(medianStr);
  }
  else {
       median = (double) gradeArray[gradeCount/2];
       medianStr = Double.toString(median);
      txtMedian.setText(medianStr);
  }
         //start of the average
               for (double i : gradeArray){
                   sum += i;
               }
               mean = sum / gradeCount;
               meanStr = Double.toString(mean);
               txtMean.setText(meanStr);

       }
     catch(NumberFormatException | HeadlessException e)  //catches bad data
                  {
                  JOptionPane.showMessageDialog(this, "Your input must be numeric!", "Bad Data!", JOptionPane.ERROR_MESSAGE);
                  }
     }
     while(gradeCount <= 25);

      }                                       
xenteros
  • 15,586
  • 12
  • 56
  • 91
Erik B
  • 13
  • 4
  • 1
    I think you have an integer division problem. – Tim Biegeleisen Dec 06 '16 at 03:26
  • 2
    as well as a code formatting problem. Good formatting including using an indentation style that is uniform and consistent will help others (**us**!) to better understand your code, and more importantly, it will help **you** to better understand your code and thus fix your own bugs. Also it shows that you're willing to put in extra effort to make it easier for the volunteers here to help you, and that effort is **much** appreciated. – Hovercraft Full Of Eels Dec 06 '16 at 03:27
  • @TimBiegeleisen Could you elaborate on my integer problem or tell me where the original post of this is? If you are referencing this (http://stackoverflow.com/questions/16663801/calculate-median-in-an-array-can-someone-tell-me-what-is-going-on-in-this-line?rq=1) then I think you are mistaken on the issue, I have mine sorted and if statement to determine odd/even for the Median where the other post doesn't and pretty much only sorts it I guess hoping if it is just going to be the right size. Mine has to work on both even and odd. Similar issues but different, wouldn't call it duplicated. – Erik B Dec 06 '16 at 03:32
  • 1
    Refresh your screen and you'll see a link to the duplicate. You're doing int division which must return an int. Don't do that -- do double division instead. Please read the dup link. – Hovercraft Full Of Eels Dec 06 '16 at 03:33
  • 1
    When you divide integers in Java, you don't get a decimal component, which instead is truncated (thrown away). Check your math used for computing the median, and you should see this. – Tim Biegeleisen Dec 06 '16 at 03:33
  • @TimBiegeleisen Alright I have taken a long look back at the section and I don't see where I am using an int at all, I have been declaring doubles I think just about this whole program just so I could use decimals. Unless using length % 2 converts my declared double array into an int then I guess that is my issue and I need to like double.parsedouble it? I don't just jump the gun and ask these questions at every issue, program is due later tomorrow and ive been staring at basically a wall for a few days not making progress. I am trying but I just don't see it. – Erik B Dec 06 '16 at 03:55
  • @ErikB To force the division to not be in "int" mode, just make the numerator or denominator `double`, e.g. `(double)length / 2` – Tim Biegeleisen Dec 06 '16 at 03:56
  • @TimBiegeleisen Thank you for the reply but don't I already have those so: median = ((double)gradeArray[gradeArray.length/2] + (double)gradeArray[gradeArray.length/2 - 1])/2; the (double) is forcing it to be a double for the equation if I put more like around [(double)gradeArray] then I get a lossy conversion but I don't understand how it is an int at all in the first place since the array itself is a double when I declared it. – Erik B Dec 06 '16 at 04:06
  • @ErikB Your division looks OK actually. There must be some other problem there, or the code you showed us above is not what is really running. – Tim Biegeleisen Dec 06 '16 at 04:15
  • @TimBiegeleisen I am not sure I follow about having other code, what I pasted was all in my button to calculate and prompt for tall this info, the only other thing is an exit button with System.exit(0);. I did however change a few things since you said the double with lengths and couldn't put (double)length where it was gradeArray.length so I made it a variable that is a double but got a lossy conversion error here is a screen shot( hope those are allowed?) https://gyazo.com/5904b48f3963ab523403749696b19c1b I can promise that I don't use that txtbox setText for it anywhere on median. – Erik B Dec 06 '16 at 04:20
  • Can you edit your question to show a code snippet which reproduces this problem? Make sure the code can be copied verbatim to another IDE for testing. – Tim Biegeleisen Dec 06 '16 at 04:24
  • @TimBiegeleisen ok I updated the post to include a snippit of what I have going on now, not sure what you mean IDE but everything is literally copied and pasted. – Erik B Dec 06 '16 at 04:31
  • @ErikB "IDE" means "Interactive Development Environment." ...which is just a big fancy name for the program you are using to write your code in. – Travis Dec 06 '16 at 04:51

1 Answers1

2

Two problems.

First, your do-while loop is missing braces to denote the body. (is this in your original code? or only what you posted here?)

Second, you are declaring gradeArray as a primitive array, but using its length to calculate an updated median every iteration. The length of a primitive array never changes from the time it is instantiated--it is not dependent on how many elements have been added. In other words, gradeArray.length is always 25 (in your example), regardless of how many indices you have actually populated with grades.

To solve the first problem, just add braces around everything after do and before while.

To solve the second problem, you should calculate the median using gradeCount as the "length" of your array, rather than the full (static) length of the primitive array.


EDIT:

...also, I just noticed that your sort is over the full array (so all 25 indices). This may also be causing problems, since the it will consider the "empty" indices (which actually have a default value of 0.0) as part of the elements to sort. Solve this problem in a similar way. Only sort the portion of the array that actually has grades you have entered--i.e. use this method signature instead. E.g.

Array.sort(gradeArray, 0, gradeCount);

SECOND EDIT:

A third problem (that I think is unrelated, but still important to fix) is that the line if (boxInput >= 0) should instead be if (gradeCount < 25). ...assuming that this line is intended to do what the comment says it does: "makes the check for how many grades are entered".

Travis
  • 2,135
  • 17
  • 29
  • so I am going to focus on more of the second part before the do-loop since the loop works and im more worried about getting correct numbers right now, should I be replacing the length with just my gradeCount then? and its as simple as that? – Erik B Dec 06 '16 at 04:33
  • Basically. Replace `gradeArray.length` with `gradeCount` wherever you calculate the median. Also make sure to fix the `Arrays.sort`. – Travis Dec 06 '16 at 04:37
  • @ErikB Also, do you mean to say that your actual source code (not only what you posted here) does not have braces around the body of the `do-while` loop? – Travis Dec 06 '16 at 04:37
  • Holy shit thank you! I was very lost gonna be updating soon (laptop isn't that great so started commenting from desktop). as for the do loop I do not have a { right after the do, my next { is right after try to start the try catch. – Erik B Dec 06 '16 at 04:47
  • @ErikB Glad it worked! And in this very particular case, your `do-while` loop works without the braces because of the monolithic `try-catch` block inside the loop. However, for the future, you should always use braces for a `do-while` loop--it helps prevent "dumb" mistakes from happening. – Travis Dec 06 '16 at 04:50
  • alright yeah I did mess up the boxinput for the if statement so that's fixed and yeah I will be putting brackets around the do-while loop now. Thanks for taking the time and looking. – Erik B Dec 06 '16 at 04:54
  • @ErikB No worries. And I just realized I made a mistake. `if (gradeCount >= 25)` should be `if (gradeCount < 25)` (just reversing the logic for the valid / invalid test). And on a related note, `while (gradeCount <= 25)` should be `while (gradeCount < 25)`, or else you'll have an infinite loop of sorts, since `gradeCount` can never go above 25. What actually happens is that the line `gradeArray[gradeCount] = boxInput;` will result in `ArrayIndexOutOfBoundsException` when `gradeCount` is 25. That may be caught by a `try` block higher up the call hierarchy, resulting in unexpected behavior. – Travis Dec 06 '16 at 05:09
  • Thanks for the heads up, I might be asking a little bit too much but would you know anything about getting an average from my array? Googling lead me to just keep getting what I assume was the sum / 25 (length) instead of sum / number of items. Tried using gradeCount again but got literal Infinity as my answers after that lol. Still looking into it but thought I would just go ahead and ask if it isn't too much to ask for, if it is no problem just happy I got median finally working. – Erik B Dec 06 '16 at 05:32
  • @Travis Thanks for helping here! – Tim Biegeleisen Dec 06 '16 at 05:43
  • @ErikB You are correct in that the average is equal to the sum of the valid (i.e. non-empty) elements divided by the number of elements. If the number of elements happens to be 25, then so be it. *But if your array is only partially populated*, then it will be < 25. So use `gradeCount` (which is equal to the number of elements), not `gradeArray.length`. – Travis Dec 06 '16 at 05:52
  • @ErikB Just make sure to test for the case when `gradeCount` is zero. Because you are implicitly converting `gradeCount` to a double when dividing your grades (which are doubles) by `gradeCount`, you can get some funky behavior. For example, a double has special bit sequences reserved to represent positive infinity, negative infinity, NaN, etc. Basically, just make sure you never divide a double (or a float for that matter) by zero. – Travis Dec 06 '16 at 05:53
  • @Travis Yeah I think I got it all working, I was doing some weird math but figured it out ill update the code up above one more time then probably go to bed. Thanks for everything. – Erik B Dec 06 '16 at 05:55
  • @ErikB No worries. And if your curious, I just looked up the IEEE 754 standard for floating point division by zero. In keeping to the principle of "gradual underflow," floating point division by zero does not result in an error. Rather, if the numerator is positive, it results in positive infinity. If the numerator is negative, it results in negative infinity. And if the numerator is also zero, it results in NaN. So that might explain why infinity was showing up. – Travis Dec 06 '16 at 05:59