Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

prostuff1

macrumors 65816
Original poster
Jul 29, 2005
1,482
18
Don't step into the kawoosh...
Hello all. I am working on some homework and i can't seem to figure the whole thing out completely. I have ben going back and forth and just cant seem to figure it out.

OK, an explination of what i need to do:
I need to get the output of this little program to look like this:
How many numbers? 100
How many intervals? 10

Histogram
--------------------------------------------------------
1 ****(4)
2 ******(6)
3 ***********(11)
4 *****************(17)
5 **************************(26)
6 *************************(25)
7 *******(7)
8 ***(3)
9 (0)
10 *(1)
--------------------------------------------------------

And The program performs the following actions:

1. Ask the user to enter the number of numbers that will be generated and the number of intervals that will be used in the histogram, and input the two values;

2. Generate the required number of pseudo-random numbers by using the double[] Generator.getData(int n), which, given the number of numbers to generate, n, returns an array of double of size n containing the generated numbers;

3. Compute the range of data values (by finding the maximum and the minimum and taking their difference); then compute the width of each equally-sized interval (by dividing the whole range by the number of intervals specified by the user); finally, compute the number of data numbers falling in each interval and store these frequencies in an array of integers;

4. Output the histogram of the data as displayed in the sample run above: each bar starts with an index (1 through the number of intervals), followed by a number of '*' equal to the number of numbers in that range, followed by the number of '*' in parentheses.

While that does not seem to hard i seem to be having some trouble.

Right now this is what my program looks like:
Code:
import java.util.Scanner;
public class messwith {

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		Scanner keyboard = new Scanner(System.in);
		
		System.out.print("How many numbers? ");
		int numbers = keyboard.nextInt();
		System.out.print("How many Intervals? ");
		int intervals = keyboard.nextInt();
		double[] rand_num = Generator.getData(numbers);
		double max = max(rand_num);
		double min = min(rand_num);
		double inter_size = intervalSize(max, min, intervals);
		int[] amount = numbers(rand_num, inter_size, min, intervals);
		outPutResults(numbers, rand_num, amount);
	}
	private static double max(double[] rand_num)
	{
		double max = 0;
		for(int index = 0; index < rand_num.length; index++)
		{
			if(rand_num[index] > max)
			{
				max = rand_num[index];
			}
		}
		return max;
	}
	private static double min(double[] rand_num)
	{
		double min = 0;
		for(int index = 0; index < rand_num.length; index++)
		{
			if(rand_num[index] < min)
			{
				min = rand_num[index];
			}
		}
		return min;
	}
	private static double intervalSize(double max, double min, int intervals)
	{
		double range = max - min;
		double width = range/intervals;
		return width;
	}
	private static int[] numbers(double[] rand_num, double inter_size, double min, int intervals)
	{
		int[] numbers = new int[intervals];
		int index = 0;
		double count_interval = min + inter_size;
		
		while(index < intervals)
		{
			int begin = 0;
			int count = 0;
			while(begin < (intervals-1))
			{
				if(rand_num[begin] >= min && rand_num[begin] < count_interval)
				{
					count++;
				}
				numbers[index] = count;
			}
		}
		return numbers;
	}
	private static void outPutResults(int numbers, double[] rand_num, int[] amount)
	{
		int index = 0;
		System.out.println("Histogram");
		System.out.println("--------------------------------------------------------");
		while(index < numbers)
		{
			System.out.print((index + 1) + " ");
			while(index < rand_num[index])
			{
				System.out.print("*");
			}
			System.out.println("(" + rand_num[index] + ")");
			index++;
		}
		System.out.println("-------------------------------------------------------");
	}
}

While i thought this would work i seem to be having troubles. I cant seem to get it to print anything besides this:
How many numbers? 10
How many Intervals? 5

Histogram
--------------------------------------------------------

As you can see i have some problems in there that i cant seem to figure out. I was hopfing to get this done by friday afternoon cause this has to be turned in sunday night. I am not going to be at the school this weekend so i am trying to turn it in early.

If anyone can give me some help it would be appreciated!!!

Thanks
 

HiRez

macrumors 603
Jan 6, 2004
6,250
2,576
Western US
It seems that something is causing while(index < numbers) to evaluate to true on your first test. Because you have just set index to be zero, that must mean something has caused the numbers variable to be less than or equal to zero, so I would investigate that first.

But, something else is wrong here. Even if that while loop never gets executed, you should see both lines of dashes printed out, because there is no way to break out of that method before it exits naturally by falling off the end. Because of that, I suspect your program must be terminating prematurely with some error or crash -- is there any error message being printed out?

Also "output" is one word, not two, so it shouldn't be intercapped. :)
 

prostuff1

macrumors 65816
Original poster
Jul 29, 2005
1,482
18
Don't step into the kawoosh...
HiRez said:
It seems that something is causing while(index < numbers) to evaluate to true on your first test. Because you have just set index to be zero, that must mean something has caused the numbers variable to be less than or equal to zero, so I would investigate that first.

But, something else is wrong here. Even if that while loop never gets executed, you should see both lines of dashes printed out, because there is no way to break out of that method before it exits naturally by falling off the end. Because of that, I suspect your program must be terminating prematurely with some error or crash -- is there any error message being printed out?

Also "output" is one word, not two, so it shouldn't be intercapped. :)

Thanks for the help.

It does not give me any other errors cause the program never terminates. I have let it run for a couple minutes and i still cant get anything more then what i put in my first post.

As for output thanks. I was typing fast and did not realize that i had capitalized it.

I will look at my program again and keep the suggestions coming.

thanks
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
Your program seemed to be pretty slow, and an important lesson in programming is to keep it simple.;)
Basically I rewrote the entire thing into the main method as that was easier to work with (especially as it goes through in a fixed order), I couldn't use the generator class as I guess that's a specific special one for your course so you'll have to re-add it back in, also you'll need to get it to print the values as you want them, currently it goes and prints how many values there are in each interval.

I hope this is useful :)
Code:
import java.util.Scanner;
import java.util.Random;
public class messwith {
	
	/**
	* @param args
	 */
	public static void main(String[] args){
		Scanner keyboard = new Scanner(System.in);		
		System.out.print("How many numbers? ");
		int numbers = keyboard.nextInt();
		System.out.print("How many Intervals? ");
		int intervals = keyboard.nextInt();
		//NEW CODE
		Random rGen=new Random();//creates a random number generator.
		double[] rand_num = new double[numbers];//creats an array to store them in.
		for(int count=0;count<numbers;count++){
			rand_num[count]=rGen.nextDouble();
		}
		//now find the max,min values,
		double max=rand_num[0];
		double min=rand_num[0];
		for(int count=1;count<numbers;count++){
			if(rand_num[count]>max){
				max=rand_num[count];
			}
			if(rand_num[count]<min){
				min=rand_num[count];
			}
		}
		//System.out.println("max="+max+", min="+min); I used this for testing, you may want to re-enable it.
		double intervalSize=(max-min)/intervals;
		//System.out.println("Interval size="+intervalSize); I also used this for testing, you may want to re-enable it.
		int[] Results=new int[intervals];//counts of the values in each interval are stored in this array
		for(int count=0;count<numbers;count++){//processes the rand_num array
			Double CValue=(rand_num[count]-min)/intervalSize;
			int MEnt=CValue.intValue();
			if(MEnt==intervals){//to subtract 1 from the final value so it goes in the right group.
				MEnt--;
			}
			Results[MEnt]++;
		}
		System.out.println("A histogram of the results");
		for(int count=0;count<intervals;count++){
			System.out.println(Results[count]);
		}
	}
}

You will need to interate a print, inside the final for block to print the stars that you want.
 

prostuff1

macrumors 65816
Original poster
Jul 29, 2005
1,482
18
Don't step into the kawoosh...
thanks you very much for the help Eraserhead!!

Thanks for the help.

I kinda knew what i was doing but i ended up asking the teacher what exactly the program was supposed to do cause the direction were kinda vague on this one. Once i knew what the program was supposed to do i had a better idea what was going on.

If you dont mind could you explain (or anyone else) what this piece of code is exactly doing:
Code:
Double CValue = (rand_num[count]-min)/interval_size;
			int MEnt = CValue.intValue();
			if(MEnt == intervals)
			{
				MEnt--;
			}
			result[MEnt]++;
I am not quite sure wgat exactly it is doing.

Thanks
 

Svennig

macrumors member
Jan 20, 2006
69
0
Disclaimer: I'm away from home at present and don't have access to a machine to check if this compiles and executes properly. However, it will do as a proof of concept :)

This code becomes MUCH easier to understand if you sort the array (plus it's much quicker for larger arrays)

Code:
import java.util.Scanner;
import java.util.Random;
public class messwith {
	
	/**
	* @param args
	 */
	public static void main(String[] args){
		Scanner keyboard = new Scanner(System.in);		
		System.out.print("How many numbers? ");
		int numbers = keyboard.nextInt();
		System.out.print("How many Intervals? ");
		int intervals = keyboard.nextInt();
		//NEW CODE
		Random rGen=new Random();//creates a random number generator.
		double[] rand_num = new double[numbers];//creats an array to store them in.
		for(int count=0;count<numbers;count++){
			rand_num[count]=rGen.nextDouble();
		}

		//Iterating through the array to find the maximum and 
                //minimum is inefficient, as it scales O(n).
		//
		//A better way of doing it is to sort the array, which gives
		//much better performance, and then take the first and last values.
		//This also makes it MUCH easier to do the groupings at the end. 
		Arrays.sort(rand_num);
		//now find the max,min values,
		double max=rand_num[rand_num.length - 1];
		double min=rand_num[0];
		
		//Now, we must calculate the interval size and make an array to store
		//the results. 
		double intervalSize=(max-min)/intervals;
		int[] Results=new int[intervals];
		//Set the contents of the results array to zeros
		Arrays.fill(Results, 0);

		//Iterate through the results, grouping them. 
		//
		//Because the set is sorted this is quite simple. The 
		//array of values is in ascending numerical order. Therefore
		//we need to check whether it is between the lower and upper
		//bounds of the interval and then count them. 
		//
		//If we go over the bounds, we increment the interval and continue. 
		double highValue = intervalSize + min;
		int currentInterval = 0;
		for(int count=0;count<numbers;count++){
			
			double value = rand_num[count];
			
			//If the value is less than the current highest
			//acceptable value for the interval, then we 
			//increment the number of results in the interval
			if(value =< highval) {
				Results[currentInterval]++;
			}	

			//If the value is greater than the current 
			//highest value, then we have moved into the next
			//Interval. So, we must increment the high value, 
			//increment the currentInterval, increment the results
			//of the new interval

			if(value > highval) {
				currentInterval++;
				highValue += intervalSize;
				Results[currentInterval]++;
			}	
		}
		

System.out.println("A histogram of the results");
		for(int count=0;count<intervals;count++){
			System.out.println(Results[count]);
		}
	}
}

Same comment as previous, you will need to do some work to make the stars work ;)
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
prostuff1 said:
Thanks for the help.

I kinda knew what i was doing but i ended up asking the teacher what exactly the program was supposed to do cause the direction were kinda vague on this one. Once i knew what the program was supposed to do i had a better idea what was going on.

If you dont mind could you explain (or anyone else) what this piece of code is exactly doing:
Code:
Double CValue = (rand_num[count]-min)/interval_size;
			int MEnt = CValue.intValue();
			if(MEnt == intervals)
			{
				MEnt--;
			}
			result[MEnt]++;
I am not quite sure wgat exactly it is doing.

Thanks

I guess it's irrelavent as Svennig has done it in a better way than me, his method is better as it only iterates through the data once not 3 times, and it also is easier to understand how it checks the interval.

In my method above the first line takes off the minimum value and then divides by the interval size, this gives you a double between 0.0 and the number of intervals, you take off the minimum as the intervals are effectively shifted down by that amount. Then this is converted to an integer which takes off the decimal places of the number. (This gives the line of the Results array it is added to at the end.) However for the maximum value it will have exactly the number of interval's which means it's too big for the array so in that case you need to subtract 1 so it goes into the largest group.

then finally you add one to the value in the Results array.
 

MarkCollette

macrumors 68000
Mar 6, 2003
1,559
36
Toronto, Canada
Two things pop to mind:

1. Your min method should default its min variable to a very large value, like Double.MAX_VALUE, instead of zero. While you're in there, change the max method's max default value from zero to Double.MIN_VALUE.

2. In the numbers method, I don't see the index variable being incremented.
 

mrichmon

macrumors 6502a
Jun 17, 2003
873
3
Eraserhead said:
I guess it's irrelavent as Svennig has done it in a better way than me, his method is better as it only iterates through the data once not 3 times, and it also is easier to understand how it checks the interval.

However Svennig's approach relies on sorting the Array. Sorting this array is going to be an expensive process -- according to the Java API docs this is O(n*log(n)). This is a common CS problem and the most efficient solution does not involve sorting the Array.

You want to do two passes traversals of the array. First pass finds max and min values -- set foundMax and foundMin values to the first value of the array then iterate over the array comparing the foundMax and foundMin to the current element. If the current element is greater than foundMax set foundMax to current element value. If the current element is greater than foundMin then set foundMin to current element value.

Then, calculate the interval width and create an array of histogram bins.
Second traversal, subtract minValue from current element then divide by interval width. This will give you the bin number that should be incremented.

Once the second traversal is complete print the histogram based on the contents of the histogram bins.

This algorithm is O(2n).
 

mbabauer

macrumors regular
Feb 14, 2006
105
0
Oh, this brings me back to the "good ol' days of collage". Boy I miss those totally irrelavant projects that teach you nothing.

Ok, let me see if I can restate the problem: You need a app, that when given an interval (number of samplings) and a number (the total number of readings) it will calculate a nifty histogram showing only the intervals.

My first question is: What happens to the numbers that do not fall in the interval? Are they thrown out, calculated into some final "average"...it didn't seem too clear.

That aside, my suggestion(s) would be such:
  1. Dont have a separate min and max method. This is WAY too much work. I know it seems like good OOP to split them out, but in practice it creates more work and a slower program. It also gives you more chances to screw up. Have one for loop, and two variables (min and max) set to the first value in the array. As you iterate the for loop, check each number in the array to see if its > max or < min, and set them accordingly
  2. You seem to be using this "number" variable a lot. Note that all arrays, being objects themselves, have a property called "length". Length is the number of elements in the array, so why keep passing it around if you don't have too. Again, doing so provides more opportunities to screw up
  3. Get yourself a good IDE with a debugger, and learn to use it. When you are first starting out, its OK to use notepad/TextMate, but as you progress, a good IDE is invaluable. If you get Eclipse, and have an Intel-based mac, get the 3.2 release, as its Universal Binary and the 3.1 doesn't work at all. Eclipse can be found at http://www.eclipse.org
  4. If an IDE is totally out of the question, and you are stuck with a text editor and your JDK, then use my old debug technique: Print, print, print. Put a System.out.println() on ever other line! It gets messy, but this is a temporary thing. Print out variables and their values, print out markers saying stuff like "I am about to execute XXX" and "Just did XXX", or simply print "At line XXX". This will help you to learn to visualize what the program IS doing vs. what you THINK it is doing

This is the best advise I can give you, other than stick with it. Its tempting to have someone just write the code for you, but if you are looking at a career in the field, you have to ask yourself "What am I really learning here...".

Good luck
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.