Working with doubles, having some troubles

Please support our C++ advertiser: Intel Parallel Studio Home
Reply

Join Date: Mar 2008
Posts: 6
Reputation: Ripture is an unknown quantity at this point 
Solved Threads: 0
Ripture Ripture is offline Offline
Newbie Poster

Working with doubles, having some troubles

 
0
  #1
Mar 16th, 2008
First of all, forgive the corny title, I couldn't resist once I thought of it.

I have a small assignment for a statistics class that had been giving me a little bit of trouble. How we did the assignment was left up to the students since it is a stats class and not a programming class. I was fairly sure I could easily do what I needed to with C++ so I gave it a whirl but started hitting weird snags that kept it from working properly.

I'll save you from the specifics of the assignment and get right down to where the weird stuff started happening. I have an array of size 20000 and I initially give all the values a 0. I then go through a user-specified number of "jumps" where the program goes through each of the 20000 values and moves them 0.1 positive or 0.1 negative with a 50/50 chance of each happening for each jump. Any of you familiar with probability curves can probably recognize that this would end up looking something like a bell curve after enough jumps. At this point, I go ahead and get it to spit out the 20000 values so I can see what some of them look like. Most of them seem fine but every 10 or 20 values, I don't see the expected ##.# format like it should, only ever adding or subtracting 0.1. I see numbers like 1.258384e-017 and the such. That's anomaly number 1. It's not a real big issue, these values sort of just fall off the map and don't get counted.

Now on to the part that really just doesn't work. After this, I go through each of the 20000 values and compare them to a "min" and "max", each initially set at 0. For each value less than min, min becomes that value and the same for max. It seems like it finds the minimum and maximum values in the array well. The next part of the assignment is to split this range into 20 sections and count how many numbers fall into these sections so I can get points in a distance-to-points graph that will resemble the expected bell curve. Obviously, the division won't always yield a nice and neat ##.# format that I can easily use for comparing. Most of the time, it's values like 1.524333. I can't compare this to the values that are in the array, values like 1.4 and -2.6. I did some casting trickery and cut off the excess numbers to turn 1.524333 into 1.5. There may be another way to do this but this is the one that I figured out and it seems to work. Now I have to count the numbers that match in each of the sections and add 1 to the corresponding section in another array, sized 20. It does not seem to like comparing the two doubles together, at least not in the way that I formed the numbers. The results would be highly erratic and incoherent. Similar to how I cut down the first number, I did some more int casting here so that I would be comparing ints and not doubles. That seemed to do the trick and the output seems good enough now. Is there something else I could have done to fix this or is it just a property of doubles that you have to work with?



Sorry for the wall of text. If something is too confusing and you still want to try and help me out, just let me know and I'll try to explain it better. I will include the source in this post as well. The assignment is due tomorrow so this will really be just for me to know. Like I said at the end of the post, the program works well enough for me.

  1. #include <iostream>
  2. #include <iomanip>
  3. #include <time.h>
  4. #include <math.h>
  5.  
  6. using namespace std;
  7.  
  8. double trunc(double a);
  9. int rect(double a);
  10.  
  11. int main()
  12. {
  13. double diff[20000],rectd,rectb;
  14. double max,min,bin,times=0,jump=0;
  15. int bins[20];
  16. double z=0,currbin=0;
  17.  
  18. for(int x=0;x<20000;x++)
  19. {
  20. diff[x]=0; //Initialize the array to 0
  21. }
  22.  
  23. srand(time(NULL)); //Give the random timer a seed
  24.  
  25. cout<<"How many jumps?"<<endl<<":";
  26. cin>>times;
  27.  
  28. for(int i=0;i<times;i++)
  29. {
  30. for(int x=0;x<20000;x++)
  31. {
  32. jump=rand()%10; //Generate a value between 0 and 9
  33. if(jump>4)
  34. {diff[x]+=0.1;} //50% chance to jump +0.1
  35. else
  36. {diff[x]-=0.1;} //50% chance to jump -0.1
  37. }
  38. }
  39.  
  40. for(int x=0;x<20000;x++)
  41. {
  42. if(diff[x]<min){min=diff[x];} //Find the maximum
  43. if(diff[x]>max){max=diff[x];} //and minimum
  44. }
  45.  
  46. cout<<"The minimum value is "<<min<<" and the maximum value is "<<max<<endl;
  47.  
  48. bin = (max + (min*-1.0))/19; //Split the range into 20 sections
  49.  
  50. cout<<"The values will be separated into 20 bins, each "<<bin<<" units apart."<<endl;
  51.  
  52. for(int m=0;m<20;m++)
  53. {
  54. currbin=min+(bin*z); //Select the current section
  55. if((m>0)&(m<19))
  56. {
  57. currbin=trunc(currbin); //Cut off excess decimals if needed
  58. }
  59. for(int x=0;x<20000;x++)
  60. {
  61. rectd=rect(diff[x]); //Create accurate values to
  62. rectb=rect(currbin); //compare correctly
  63. if(rectd == rectb){bins[m]++;} //If the value is in the section, add
  64. } //one to that section in the bin array
  65. z++;
  66. }
  67.  
  68. cout<<"The final values in the array are:"<<endl;
  69.  
  70. z=0;
  71. for(int m=0;m<20;m++)
  72. {
  73. currbin=min+(bin*z);
  74. if((m>0)&(m<19))
  75. {
  76. currbin=trunc(currbin);
  77. } //Display the values accumulated in the
  78. cout<<setw(5)<<left<<currbin //bins array.
  79. <<": "<<bins[m]<<endl;
  80. z++;
  81. }
  82.  
  83. system("pause");
  84. return 0;
  85. }
  86.  
  87.  
  88. int rect(double a)
  89. {
  90. int b;
  91. a*=3;
  92. b=int(a);
  93. return b;
  94. }
  95.  
  96. double trunc(double a)
  97. {
  98. int s=0;
  99. a/=0.1;
  100. s=int(a);
  101. a=double(s);
  102. a*=0.1;
  103. return a;
  104. }
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 15,348
Reputation: Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute 
Solved Threads: 1462
Team Colleague
Featured Poster
Ancient Dragon's Avatar
Ancient Dragon Ancient Dragon is offline Offline
Still Learning

Re: Working with doubles, having some troubles

 
0
  #2
Mar 16th, 2008
You have come across a common problem that is inherent in the way floats and doubles are represented in memory. There are many numbers that can't be represented exactly.

One way around your problem is to use only long integers with implied decimal point. For example instead of 1.23 in double you could use 123 integer.

Another possible solution is to use boost math libraries. I hav enot used it myself do don't know if it will solve your problem or not.

Yet another solution is to use a different language, such as FORTRAN which is designed for mathimatical problems.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 1,674
Reputation: vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold 
Solved Threads: 193
vmanes's Avatar
vmanes vmanes is offline Offline
Posting Virtuoso

Re: Working with doubles, having some troubles

 
0
  #3
Mar 17th, 2008
two things you need to do to fix what you've got:

Initialize the bins array - you start your counting with random junk in the array
int bins[20] = { 0 }; Initialize min and max to the first element of the diff array. You say in your text that you set them to 0, but you haven't. And in general, that may not be sufficient. You should always set the min and max to a value from the data set to ensure a valid comparison.
  1. min = diff[0];
  2. max = diff[0];
  3. for(int x=0;x<20000;x++)
  4. {
  5. if(diff[x]<min){min=diff[x];} //Find the maximum
  6. if(diff[x]>max){max=diff[x];} //and minimum
  7. }
"We Americans got so tired of being thought of as dumb by the rest of the world that we went to the polls last November and removed all doubt."
~~~~~~~~~~~~~~~~~~
Looking for an exciting graduate degree? Robotics and Intelligent Autonomous Systems (RIAS) at SDSM&T See the program brochure here.
Reply With Quote Quick reply to this message  
Join Date: Mar 2008
Posts: 6
Reputation: Ripture is an unknown quantity at this point 
Solved Threads: 0
Ripture Ripture is offline Offline
Newbie Poster

Re: Working with doubles, having some troubles

 
0
  #4
Mar 17th, 2008
Argh, you are absolutely correct, vmanes. I must have omitted the code setting min and max to 0 but I can see how setting them to values in the array instead would be a better choice.

As far as not initializing the bins array, that was just stupid on my part. I don't know how the results I got were looking good without doing that first.

Oh and one last thing, I can initialize an array like that?

int bins[20] = { 0 };
Does that set all 20 values in the array to 0? Thanks for your input on this.
Last edited by Ripture; Mar 17th, 2008 at 9:48 am.
Reply With Quote Quick reply to this message  
Join Date: Aug 2007
Posts: 1,674
Reputation: vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold vmanes is a splendid one to behold 
Solved Threads: 193
vmanes's Avatar
vmanes vmanes is offline Offline
Posting Virtuoso

Re: Working with doubles, having some troubles

 
0
  #5
Mar 17th, 2008
Oh and one last thing, I can initialize an array like that?
int bins[20] = { 0 };

Does that set all 20 values in the array to 0? Thanks for your input on this.
Yes, yes. Arrays are initialized with an "initializer list" which is enclosed in curly brackets, individual values separated by commas. You can set the list to be exactly the number of values the array holds, or any lesser number of values. Any uninitialized elements will be set to 0. If you put too many elements in the list, you will get a compilation error.

So, (for me, anyway) the most common initialization of an array, to ensure it does not contain random memory patterns, is the list you see above.
"We Americans got so tired of being thought of as dumb by the rest of the world that we went to the polls last November and removed all doubt."
~~~~~~~~~~~~~~~~~~
Looking for an exciting graduate degree? Robotics and Intelligent Autonomous Systems (RIAS) at SDSM&T See the program brochure here.
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Other Threads in the C++ Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC