Dividing Variables into "bins"

Pages: 123
Aug 4, 2011 at 11:38pm
closed account (zbREy60M)
Hello! I'm making a program that creates stars called "gravitars" and calculates their slowing frequency over a number of years. All of that is done!

The problem now:

I need to divide the frequencies into equally spaced bins into logarithm (base 10). Then, for each of my fake gravitars, work out which bin it lands in and add to that bin the value of h. At the end of this process, I will have a list of frequency values for each bin, and the sum of all the "h" values for that bin.

Where 'h' is a variable dependent on the frequency.

How do I even go about doing something like this? I've tried "grouping" the gravitars together. I'm quite new at C++ and need a point in the right direction.
Aug 5, 2011 at 12:25am
Suppose the frequencies you're interested in are between 0 and 1E+300. You have to make a histogram with 300 buckets, where the first bucket counts frequencies in the range [0;10), the second counts frequencies [10;100), and so on.
You can do something like
1
2
3
4
5
unsigned histogram[300];
for (size_t a=0;a<gravitars.size();a++){
	double f=gravitars[a].frequency();
	histogram[size_t((f<1)?0:log10(f))]++;
}
Aug 5, 2011 at 12:31am
closed account (zbREy60M)
That looks really good.

I don't really understand how what you typed works, though. By being a histogram like that, can I just cout the data? I need to actually get a final histogram graph, and I was putting the frequencies that I generated in a .txt file and then using GNUplot. What you're doing looks foreign to me.

Thanks for the help, btw. I know you don't get anything from this!
Aug 5, 2011 at 1:36am
By being a histogram like that, can I just cout the data?
Of course.
Note that I forgot to initialize the array.
Aug 5, 2011 at 1:49am
closed account (zbREy60M)
I'm not really sure what some of your syntax is saying. Specifically the last line.
Last edited on Aug 5, 2011 at 1:53am
Aug 5, 2011 at 2:00am
closed account (zbREy60M)
In fact, I took your code and modified it as such:

1
2
3
4
5
6
unsigned histogram[300];
for (size_t a=0; a < R; a++)
{
	double f = hxrf;
	histogram[size_t((f<1)?0:log10(f))]++;
}


Where "R" is the number of gravitars that I have, and "hxrf" is the h variable I mentioned earlier (after some rounding and manipulation). I then proceeded to output this to a .txt file and this was the result:

0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8
0043DAD8

I have no idea what this mean. I would try to fix it, but I'm not sure what I did wrong, because I don't understand what your code is about. I can't seem to find any help on google about it either.
Aug 5, 2011 at 2:40am
You're supposed to print it like this:
1
2
for (int a=0;a<300;a++)
    std::cout <<histogram[a]<<std::endl;
Aug 5, 2011 at 2:57am
closed account (zbREy60M)
alright. I removed the loops from the histogram array and your cout function you just gave me, because my entire program is just a for loop that I have run "R" times, so i figure having the loop within the loop was a bad idea. Should I not have done that?

Second question: When I try to run my program now your std::cout line gives me the error: "subscript is not of integral type" I have no clue what that means.

Thanks for being patient... :/

Edit: I changed it to read histogram[300] and it ran, but just gave me the 300th member of the array, apparently. But when I put in the counter variable, it gives me the above error.
Last edited on Aug 5, 2011 at 3:02am
Aug 5, 2011 at 3:17am
i figure having the loop within the loop was a bad idea
Never forget: premature optimization is the root of all evil.

Second question: When I try to run my program now your std::cout line gives me the error: "subscript is not of integral type" I have no clue what that means.
You can't change the int in the loop I gave you in my previous post to neither float nor double. You can change it to short, long, unsigned, and a few others without any gain whatsoever. Don't change it to char.

read histogram[300]
You're accessing invalid memory.
There are no shortcuts in C++ when it comes to handling arrays, unlike whatever language you may have used before (I'm guessing Matlab or some other scientific software. Definitely something inspired by functional programming). If you want to print the contents of an array, you have to iterate over the array and print each element. If you want to add two arrays, you have to iterate over them (making sure they're the same size, of course) and add each element.
Aug 5, 2011 at 3:23am
closed account (zbREy60M)
Ive never used any other languages before. I just read the first 5 chapters of C++ for dummies. That might be why I don't understand anything you're saying. But I'm almost done with this project! I just need this last little bit to fall into place...
Aug 5, 2011 at 5:14pm
closed account (zbREy60M)
"Second question: When I try to run my program now your std::cout line gives me the error: "subscript is not of integral type" I have no clue what that means.
You can't change the int in the loop I gave you in my previous post to neither float nor double. You can change it to short, long, unsigned, and a few others without any gain whatsoever. Don't change it to char."

What does that mean?
Aug 5, 2011 at 5:22pm
closed account (zbREy60M)
I finally got it to iterate through the array and print what the things within the array, but I am just getting the same number over an over again... And when I open up the text file I just get:

0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34
0016CC34

So, once more, I am incredibly confused. Why do I keep getting the same number? I think it is because all of the numbers I am getting fall into the same "bucket" (0->10). How do I shorten the length of the buckets?

histogram[size_t((f<1)?0:log10(f))]++;

Your line of code above gives me buckets from 0 to 10 and 10 to 100, etc, how do I get a logarithmic scale on the order of .00001s. I wish I could just modify what you gave me, but I don't have any idea what it is saying...
Aug 5, 2011 at 6:20pm
What exactly does you printing loop look like?

If you want buckets closer to zero, you can do
 
histogram[size_t((f<1E-6)?0:log10(f)+6)]++;

The line says "if the f<1E-6, then just use bucket zero; otherwise, use bucket log10(f)+6". The size_t() part converts the floating point number given inside to an integer, since only integers can be used to access arrays.
Aug 5, 2011 at 6:23pm
closed account (zbREy60M)
Here is my program "loop". It's all in one loop. I have no idea if that was a bad idea or not.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
unsigned histogram[100000];

for (int R = 0; R < m; R++)
{	

long double radius = sqrt(gen());
long double angle = gen();
long double zed = gen();
long double age = gen();
long double period = var_nor()*.001; // normal distribution of periods with a mean of 5 ms and a standard deviation of .69 mseconds 

Gravitar RadialComponents;
RadialComponents.SetRadius(radius);
Gravitar AngularComponents;
AngularComponents.SetAngle(angle);
Gravitar ZedComponents;
ZedComponents.SetZed(zed);
Gravitar AgeComponents;
AgeComponents.SetAge(age);
Gravitar PeriodComponents;
PeriodComponents.SetPeriod(period);

long double x = RadialComponents.GetRadius()*cos (AngularComponents.GetAngle()*6.283185307179586476925286766559)*15329.729; 
long double y = RadialComponents.GetRadius()*sin (AngularComponents.GetAngle()*6.283185307179586476925286766559)*15329.729;
long double z = ZedComponents.GetZed()*153.29729;
long double a = AgeComponents.GetAge() * 10000000.0 * 31556926.0; // Random number generated between 0 and 1, then multiplied by 10 millions years, multiplied by the number of seconds within a year
long double p = PeriodComponents.GetPeriod(); //p measured in seconds
long double prefrequency = 2.0 / p;
long double xde = x;
long double deltay = (y - 8500);
long double deltay2 = deltay*deltay;
long double yde = sqrt(deltay2);
long double zde = z;
long double xde2 = xde*xde;
long double yde2 = yde*yde;
long double zde2 = zde*zde;
long double dge = sqrt(xde2 + yde2 + zde2);
//WARNING:E is the  NOT mathematical constant e.
//It is the const var of ellipticity
long double Ellipse2=Ellipse*Ellipse;
const long double pi=3.1415926535897932384626433832795,
	pi4=pi*pi*pi*pi,
	pi2=pi*pi,
	G=6.673E-11;
long double beta= (32.0 * pi4 * G * 10E+44) / (2.421E+42);
int value = -4;
long double othervalue = -.25;
long double postfrequency = pow( (pow(prefrequency, value) + beta * Ellipse2 * a), othervalue);
long double h = ((4.0 * pi2 * G * 10E+44) / (8.077E+33)) * ((Ellipse * pow( postfrequency, 2)) / dge);
long double hx = h*1000000000;
long double hxr = floor (hx);
long double hxrf = hxr/1000000000;

//printf("Gravitar # %4f %16f %16f %16f %16f %16f %32f %16f %16f %16f %16f \n" , R+1 ,  x , y , z , a , p , Ellipse , prefrequency , postfrequency, dge, h, hxrf );

double f = hxrf;
histogram[size_t((f<1)?0:log10(f))]++;
std::cout << histogram[R] << std::endl;


if (myfile.is_open())
{
//	myfile << " " << x << "  " << y << "  " << z << " " << endl;
//	myfile << " " << a << "  " << p << " " << prefrequency << " " << postfrequency << endl;
//	myfile << h << "  " <<  dge << "  " << postfrequency << "  " << R+1 << endl;
	myfile << hxrf << "  " << histogram << endl;
}
}


Aug 5, 2011 at 8:14pm
You have to print the histogram in a loop of its own. And it only makes sense to print it once you've gathered all the data.

You still haven't initialized the array to zero.

You're getting garbage on your file because you're sending 'histogram' to it, which is a pointer. You have to send each element one by one.

100000 is too large a size for the histogram for two reasons:
1. The array is on the stack, which is pretty small.
2. double doesn't go higher than 1E+616, anyway.
Aug 8, 2011 at 4:20pm
closed account (zbREy60M)
You have to print the histogram in a loop of its own. And it only makes sense to print it once you've gathered all the data.

So where do I put it, exactly? Should I move the if myfile function out of the loop as well? It had worked fine previously, but I see your point in the fact that the array cant really be printed when it still doesnt have all the information in it.

You still haven't initialized the array to zero.

How do I do that?

You're getting garbage on your file because you're sending 'histogram' to it, which is a pointer. You have to send each element one by one.

I don't know what you mean by that.

1
2
3
100000 is too large a size for the histogram for two reasons:
1. The array is on the stack, which is pretty small.
2. double doesn't go higher than 1E+616, anyway. 


So question, this array histogram, does it need as many bins as gravitars I am generating? Or is the first value in the array 0-->10 and the second value in the array 10--> 100?
And everytime one of the gravitars falls into one of the "bins" if it is in the frequency range of 0--->10 it adds an integer to the first value in the array? Is that how this works?
Aug 8, 2011 at 6:18pm
So where do I put it, exactly?
At any point after you've looped through all your objects.

How do I do that?
You set each element to zero.

So question, this array histogram, does it need as many bins as gravitars I am generating?
If it did, it wouldn't be a histogram.

Evidently, it's going to be much faster if I just write it for you, so...
1
2
3
4
5
6
7
8
9
10
11
unsigned histogram[650]={0};

for (int R = 0; R < m; R++){	
	//...
}

for (int a=0;a<650;a++)
	std::cout << histogram[a] << std::endl;
if (myfile.is_open())
	for (int a=0;a<650;a++)
		std::cout << histogram[a] << std::endl;
Aug 8, 2011 at 6:43pm
closed account (zbREy60M)
Alright great! I almost had that, I was just a little bit off. I didn't know you had to initialize an array.

As a side note, do you have a paypal? You've been an immense help, no one else around me has any clue what they are doing. I wouldn't mind throwing you 25 bucks for you time and patience :)

Aug 8, 2011 at 6:52pm
That's not really necessary, but hey, I'm not about to turn down free money.
Click on my name at the top of my posts to go to my profile. My e-mail address is there.
Aug 8, 2011 at 8:16pm
closed account (zb0S216C)
Riogho wrote:
no one else around me has any clue what they are doing. (sic)

I'd watch what you say if I was you. With an attitude like that, you're lucky to even get a reply. And for the record, there's plenty of people on this forum with stacks of experience. Most experienced users on this forum have jobs and a life to attend to before posting on a forum. Think about that next time.

Wazzak
Pages: 123