I'm trying to implement a circular buffer in order to average a stream of data points generated by a pressure sensor in C running on an embedded controller. The idea is to store the last N pressure readings in the buffer while maintaining a running sum of the buffer. Average = sum / N. Should be trivial.
However, the average I'm seeing is a value that starts near the pressure reading (I preload the buffer registers with a typical value), but which subsequently trends towards zero. If I also display the sum, it too is dropping asymptotically to zero. If the pressure changes, the average moves away from zero in the direction of the pressure change, but returns to its zero trend as soon as the pressure stabilizes.
If anyone could spot the error I'm making, it would be very helpful.
#define ARRAYSIZE 100
double Sum; // variable for running sum
double Average; // variable for average
double PressureValue[ARRAYSIZE]; // declare value array
int i; // data array index
int main(void) {
while (1)
{
if (i == ARRAYSIZE) i = 0; // test index, reset if it reaches the upper boundary
Sum = Sum - PressureValue[i]; // subtract the old datapoint from running sum
PressureValue[i] = PRESSURE; // replace previous loop datapoint with new data
Sum = Sum + PressureValue[i]; // add back the new current value to the running sum
Average = Sum / ARRAYSIZE; // calculate average value = SUM / ARRAYSIZE
++i; // increment index
} // end while loop
} // end main
The averaging code takes place in an interrupt handler; I'm reading the data from the pressure sensor via I2C with interrupts triggered at the end of each I2C communication phase. During the last phase, after the four bytes comprising the pressure data have been retrieved, they are assembled into a complete reading, and then converted to a decimal reading in PSI contained in the PRESSURE variable.
Obviously , this isn't a direct cut and paste from my code, but I didn't want anyone to have to wade through the whole thing, so I've limited it to just the stuff relevant to figuring the average, and changed the variable names to be more readable. Still, I can't spot what I'm doing wrong.
Thanks for your attention!
Doug G.
I don't see anything obviously wrong with your code, but as you say, you're not providing all of it, so who knows what's happening in the rest of it (in particular, how/if you're initializing i and Sum), but the following works fine for me, which is basically the same algorithm you have:
#include <stdio.h>
#include <stddef.h>
double PressureValue[8];
double Pressures[800];
int main(void) {
const size_t array_size = sizeof(PressureValue) / sizeof(PressureValue[0]);
const size_t num_pressures = sizeof(Pressures) / sizeof(Pressures[0]);
size_t count = 0, i = 0;
double average = 0;
/* Initialize PressureValue to {0, 1, 2, 3, ...} */
for ( size_t n = 0; n < array_size; ++n ) {
PressureValue[n] = n;
}
double sum = ((array_size - 1) / (double) 2) * array_size;
/* Initialize pressures to repeats of PressureValue */
for ( size_t n = 0; n < num_pressures; ++n ) {
Pressures[n] = n % array_size;
}
while ( count < num_pressures ) {
if ( i == array_size )
i = 0;
sum -= PressureValue[i];
PressureValue[i] = Pressures[count++];
sum += PressureValue[i++];
}
average = sum / array_size;
printf("Sum is %f\n", sum);
printf("Counted %zu pressures\n", count);
printf("Average is %f\n", average);
return 0;
}
Outputs:
paul#local:~/src/c/scratch$ ./pressure
Sum is 28.000000
Counted 800 pressures
Average is 3.500000
paul#local:~/src/c/scratch$
Just one more possibility, when you say they are "converted to a decimal reading in PSI contained in the PRESSURE variable", and elsewhere, for that matter, make sure you're not getting things truncated to zero because of integer division. If you've got things "trending to zero" as you're adding more, that's something I'd be immediately suspicious of. A classic error in converting Fahrenheit to Celsius, for instance, would be to write c = (f - 32) * (5 / 9), where that (5 / 9) truncates to zero every time, and always leaves you with c == 0.
Also, as a general rule, I understand that you "didn't want anyone to have to wade through the whole thing", but you'd be surprised how many times the real problem is not in the part of the code that you think it is. This is why it's important to provide an SSCCE to ensure that you can narrow down your code and actually isolate and reproduce the problem. If you try to narrow down your code and find that you can't isolate and reproduce the problem, then it's almost certain that your issue is not being caused by the thing you think is causing it.
It is also possible your code is working exactly as intended. If you are preloading your array with typical values outside of this loop and then running this code you would get the behavior you are describing. If you are preloading the array make sure you are preloading the sum and average otherwise you are essentially measuring gauge pressure with you preloaded value as atmospheric pressure.
Related
Problem statement: I am working on a code that calculates big numbers. Hence, I am easily get beyond the maximum length of "long double". Here is an example below, where part of the code is given that generates big numbers:
int n;
long double summ;
a[1]=1;
b[1]=1;
c[1] = 1; //a, b, c are 1D variables of long double types
summ=1+c[1];
for(n=2; n <=1760; n++){
a[n]=n*n;
b[n]=n;
c[n] = c[n-1]*a[n-1]/b[n]; //Let us assume we have this kind of operation
summ= summ+c[n]; //So basically, summ = 1+c[1]+c[2]+c[3]+...+c[1760]
}
The intermediates values of summ and c[n] are then used to evaluate the ratio c[n]/summ for every integer n. Then, just after the above loop, I do:
for(n=1;n<=1760;n++){
c2[n]=c[n]/summ; //summ is thus here equals to 1+c[1]+c[2]+c[3]+...+c[1760]
}
Output: If we print n, c[n] and summ, we obtain inf after n=1755 because we exceed the length of long double:
n c[n] summ
1752 2.097121e+4917 2.098320e+4917
1753 3.672061e+4920 3.674159e+4920
1754 6.433452e+4923 6.437126e+4923
1755 1.127785e+4927 1.128428e+4927
1756 inf inf
1757 inf inf
1758 inf inf
1759 inf inf
1760 inf inf
Of course, if there is an overflow for c[n] and summ, I cannot evaluate the quantity of interest, which is c2[n].
Questions: Does someone see any solution for this ? How do I need to change the code so that to have finite numerical values (for arbitrary n) ?
I will indeed most likely need to go to very big numbers (n can be much larger than 1760).
Proposition: I know that GNU Multiple Precision Arithmetic (GMP) might be useful but honestly found too many difficulties trying to use this (outside the field), so if there an easier way to solve this, I would be glad to read it. Otherwise, I will be forever grateful if someone could apply GMP or any other method to solve the above-mentioned problem.
NOTE: This does not exactly what OP wants. I'll leave this answer here in case someone has a similar problem.
As long as your final result and all initial values are not out of range, you can very often re-arrange your terms to avoid any overflow. In your case if you actually just want to know c2[n] = c[n]/sum[n] you can re-write this as follows:
c2[n] = c[n]/sum[n]
= c[n]/(sum[n-1] + c[n]) // def. of sum[n]
= 1.0/(sum[n-1]/c[n] + 1.0)
= 1.0/(sum[n-1]/(c[n-1] * a[n-1] / b[n]) + 1.0) // def. of c[n]
= 1.0/(sum[n-1]/c[n-1] * b[n] / a[n-1] + 1.0)
= a[n-1]/(1/c2[n-1] * b[n] + a[n-1]) // def. of c2[n-1]
= (a[n-1]*c2[n-1]) / (b[n] + a[n-1]*c2[n-1])
Now in the final expression neither argument grows out of range, and in fact c2 slowly converges towards 1. If the values in your question are the actual values of a[n] and b[n] you may even find a closed form expression for c2[n] (I did not check it).
To check that the re-arrangement works, you can compare it with your original formula (godbolt-link, only printing the last values): https://godbolt.org/z/oW8KsdKK6
Btw: Unless you later need all values of c2 again, there is actually no need to store any intermediate value inside an array.
I ain't no mathematician. This is what I wrote with the results below. Looks to me that the exponent, at least, is keeping up with your long double results using my feeble only double only...
#include <stdio.h>
#include <math.h>
int main() {
int n;
double la[1800], lb[1800], lc[1800];
for( n = 2; n <= 1760; n++ ) {
lb[n] = log10(n);
la[n] = lb[n] + lb[n];
lc[n] = lc[n-1] + la[n-1] - lb[n];
printf( "%4d: %.16lf\n", n, lc[n] );
}
return 0;
}
/* omitted for brevity */
1750: 4910.8357954121602000
1751: 4914.0785853634488000
1752: 4917.3216235537839000
1753: 4920.5649098413542000
1754: 4923.8084440845114000
1755: 4927.0522261417700000 <<=== Take note, please.
1756: 4930.2962558718036000
1757: 4933.5405331334487000
1758: 4936.7850577857016000
1759: 4940.0298296877190000
1760: 4943.2748486988194000
EDIT (Butterfly edition)
Below is a pretty simple iterative function involving one single and one double precision float values. The purpose is to demonstrate that iterative calculations are exceedingly sensitive to initial conditions. While it seems obvious that the extra bits of the double will "hold-on", remaining closer to the results one would get with infinite precision, the compounding discrepancy between these two versions demonstrate that "demons lurking in small places" will likely remain hidden in the fantastically tiny gaps between finite representations of what is infinite.
Just a bit of fun for a rainy day.
int main() {
float fpi = 3.1415926535897932384626433832;
double dpi = 3.1415926535897932384626433832;
double thresh = 10e-8;
for( int i = 0; i < 1000; i++ ) {
fpi = fpi * 1.03f;
dpi = dpi * 1.03f;
double diff = fabs( dpi - fpi );
if( diff > thresh) {
printf( "%3d: %25.16lf\n", i, diff );
thresh *= 10.0;
}
}
return 0;
}
8: 0.0000001229991486
35: 0.0000010704333473
90: 0.0000100210180918
192: 0.0001092634900033
229: 0.0010121794607585
312: 0.0100316228017618
367: 0.1002719746902585
453: 1.0056506423279643
520: 10.2658853083848950
609: 103.8011477291584000
667: 1073.9984381198883000
736: 10288.9632129669190000
807: 101081.5514678955100000
886: 1001512.2135009766000000
966: 10473883.3271484370000000
I am trying to simulate the propagation of a worm across a network made of 100,000 computers. The simulation itself is very simple and I don't need any help except that for some reason, I am only getting every third random number.
Only the computers whose index modulo 1000 is less than 10 can be infected so when 1000 computers are infected, the program should be done. For some reason, my program only gets 329. When I lower the goal number and check the contents of the array, only every third computer has been changed and it is a consistent pattern. For example at the end of the array, only computers 98001, 98004, 98007, 99002, 99005, 99008 are changed even though the computers in between (98002, 98003, etc.) should be changed as well. The pattern holds all the way to the beginning of the array. When I try to get all 1000 changed, the program goes into an infinite loop and is stuck at 329.
Edit: I just discovered that if I lower the NETSIZE to 10,000 and the goal in the while loop to 100, it doesn't skip anything. Does that mean the problem has something to do with a rounding error? Someone who knows more about C than me must know the answer.
Thanks.
#include <stdio.h>
#include <stdlib.h>
#define NETSIZE 100000
double rand01();
void initNetwork();
unsigned char network[NETSIZE];
int scanrate = 3;
int infectedCount;
int scans;
int ind;
int time;
int main(void) {
initNetwork();
time = 0;
infectedCount = 1;
while (infectedCount < 1000) { //changing 1000 to 329 stops the infinite loop
scans = infectedCount * scanrate;
for (int j = 0; j < scans; j++) {
ind = (int) (rand01() * NETSIZE);
if (network[ind] == 0) {
network[ind] = 1;
infectedCount++;
}
}
time++;
}
for (int k = 0; k < NETSIZE; k++) {
if (network[k] == 1) printf("%d at %d\n", network[k], k);
}
}
double rand01() {
double temp;
temp = (rand() + 0.1) / (RAND_MAX + 1.0);
return temp;
}
void initNetwork() {
for (int i = 0; i < NETSIZE; i++) {
if (i % 1000 < 10) {
network[i] = 0;
} else {
network[i] = 2;
}
}
network[1000] = 1;
}
In the above code, I expect the code to run until the 1000 vulnerable indexes are changed from 0 to 1.
Converting comments into an answer.
What is RAND_MAX on your system? If it is a 15-bit or 16-bit value, you probably aren't getting good enough quantization when converted to double. If it is a 31-bit or bigger number, that (probably) won't be the issue. You need to investigate what values are generated by just the rand01() function with different seeds, plus the multiplication and cast to integer — simply print the results and sort -n | uniq -c to see how uniform the results are.
On my system RAND_MAX is only 32767. Do you think that might be why my results might not be granular enough? Now that you've made me think about it, there would only be 32,767 possible values and my network array is 100,000 possible values. Which corresponds about about the 1/3 results I am getting.
Yes, I think that is very probably the problem. You want 100,000 different values, but your random number generator can only generate about 33,000 different values, which is awfully close to your 1:3 metric. It also explains immediately why you got good results when you reduced the multiplier from 100,000 to 10,000.
You could try:
double rand01(void)
{
assert(RAND_MAX == 32767);
return ((rand() << 15) + rand()) / ((RAND_MAX + 1.0) * (RAND_MAX + 1.0));
}
Or you could use an alternative random number generator — for example, POSIX defines both the drand48() family of functions and
random(), with corresponding seed-setting functions where needed.
Yeah, the problem I am having is that the RAND_MAX value on my system is only 32767 and I am trying to effectively spread that out over 100,000 values which results in about only every third number ever showing up.
In my defense, the person who suggested the rand01() function has a PhD in Computer Science, but I think he ran this code on our school's main computer which probably has a much bigger RAND_MAX value.
#JonathanLeffler deserves credit for this solution.
Hi: I have been ramping up on C and I have a couple philosophical questions based on arrays and pointers and how make things simple, quick, and small or balance the three at least, I suppose.
I imagine an MCU sampling an input every so often and storing the sample in an array, called "val", of size "NUM_TAPS". The index of 'val' gets decremented for the next sample after the current, so for instance if val[0] just got stored, the next value needs to go into val[NUM_TAPS-1].
At the end of the day I want to be able to refer to the newest sample as x[0] and the oldest sample as x[NUM_TAPS-1] (or equivalent).
It is a slightly different problem than many have solved on this and other forums describing rotating, circular, queue etc. buffers. I don't need (I think) a head and tail pointer because I always have NUM_TAPS data values. I only need to remap the indexes based on a "head pointer".
Below is the code I came up with. It seems to be working fine but it raises a few more questions I'd like to pose to the wider, much more expert community:
Is there a better way to assign indexes than a conditional assignment
(to wrap indexes < 0) with the modulus operator (to wrap indexes >
NUM_TAPS -1)? I can't think of a way that pointers to pointers would
help, but does anyone else have thoughts on this?
Instead of shifting the data itself as in a FIFO to organize the
values of x, I decided here to rotate the indexes. I would guess that
for data structures close to or smaller in size than the pointers
themselves that data moves might be the way to go but for very large
numbers (floats, etc.) perhaps the pointer assignment method is the
most efficient. Thoughts?
Is the modulus operator generally considered close in speed to
conditional statements? For example, which is generally faster?:
offset = (++offset)%N;
*OR**
offset++;
if (NUM_TAPS == offset) { offset = 0; }
Thank you!
#include <stdio.h>
#define NUM_TAPS 10
#define STARTING_VAL 0
#define HALF_PERIOD 3
void main (void) {
register int sample_offset = 0;
int wrap_offset = 0;
int val[NUM_TAPS];
int * pval;
int * x[NUM_TAPS];
int live_sample = 1;
//START WITH 0 IN EVERY LOCATION
pval = val; /* 1st address of val[] */
for (int i = 0; i < NUM_TAPS; i++) { *(pval + i) = STARTING_VAL ; }
//EVENT LOOP (SAMPLE A SQUARE WAVE EVERY PASS)
for (int loop = 0; loop < 30; loop++) {
if (0 == loop%HALF_PERIOD && loop > 0) {live_sample *= -1;}
*(pval + sample_offset) = live_sample; //really stupid square wave generator
//assign pointers in 'x' based on the starting offset:
for (int i = 0; i < NUM_TAPS; i++) { x[i] = pval+(sample_offset + i)%NUM_TAPS; }
//METHOD #1: dump the samples using pval:
//for (int i = 0; i < NUM_TAPS; i++) { printf("%3d ",*(pval+(sample_offset + i)%NUM_TAPS)); }
//printf("\n");
//METHOD #2: dump the samples using x:
for (int i = 0; i < NUM_TAPS; i++) { printf("%3d ",*x[i]); }
printf("\n");
sample_offset = (sample_offset - 1)%NUM_TAPS; //represents the next location of the sample to be stored, relative to pval
sample_offset = (sample_offset < 0 ? NUM_TAPS -1 : sample_offset); //wrap around if the sample_offset goes negative
}
}
The cost of a % operator is the about 26 clock cycles since it is implemented using the DIV instruction. An if statement is likely faster since the instructions will be present in the pipeline and so the process will skip a few instructions but it can do this quickly.
Note that both solutions are slow compared to doing a BITWISE AND operation which takes only 1 clock cycle. For reference, if you want gory detail, check out this chart for the various instruction costs (measured in CPU Clock ticks)
http://www.agner.org/optimize/instruction_tables.pdf
The best way to do a fast modulo on a buffer index is to use a power of 2 value for the number of buffers so then you can use the quick BITWISE AND operator instead.
#define NUM_TAPS 16
With a power of 2 value for the number of buffers, you can use a bitwise AND to implement modulo very efficiently. Recall that bitwise AND with a 1 leaves the bit unchanged, while bitwise AND with a 0 leaves the bit zero.
So by doing a bitwise AND of NUM_TAPS-1 with your incremented index, assuming that NUM_TAPS is 16, then it will cycle through the values 0,1,2,...,14,15,0,1,...
This works because NUM_TAPS-1 equals 15, which is 00001111b in binary. The bitwise AND resulst in a value where only that last 4 bits to be preserved, while any higher bits are zeroed.
So everywhere you use "% NUM_TAPS", you can replace it with "& (NUM_TAPS-1)". For example:
#define NUM_TAPS 16
...
//assign pointers in 'x' based on the starting offset:
for (int i = 0; i < NUM_TAPS; i++)
{ x[i] = pval+(sample_offset + i) & (NUM_TAPS-1); }
Here is your code modified to work with BITWISE AND, which is the fastest solution.
#include <stdio.h>
#define NUM_TAPS 16 // Use a POWER of 2 for speed, 16=2^4
#define MOD_MASK (NUM_TAPS-1) // Saves typing and makes code clearer
#define STARTING_VAL 0
#define HALF_PERIOD 3
void main (void) {
register int sample_offset = 0;
int wrap_offset = 0;
int val[NUM_TAPS];
int * pval;
int * x[NUM_TAPS];
int live_sample = 1;
//START WITH 0 IN EVERY LOCATION
pval = val; /* 1st address of val[] */
for (int i = 0; i < NUM_TAPS; i++) { *(pval + i) = STARTING_VAL ; }
//EVENT LOOP (SAMPLE A SQUARE WAVE EVERY PASS)
for (int loop = 0; loop < 30; loop++) {
if (0 == loop%HALF_PERIOD && loop > 0) {live_sample *= -1;}
*(pval + sample_offset) = live_sample; //really stupid square wave generator
//assign pointers in 'x' based on the starting offset:
for (int i = 0; i < NUM_TAPS; i++) { x[i] = pval+(sample_offset + i) & MOD_MASK; }
//METHOD #1: dump the samples using pval:
//for (int i = 0; i < NUM_TAPS; i++) { printf("%3d ",*(pval+(sample_offset + i) & MOD_MASK)); }
//printf("\n");
//METHOD #2: dump the samples using x:
for (int i = 0; i < NUM_TAPS; i++) { printf("%3d ",*x[i]); }
printf("\n");
// sample_offset = (sample_offset - 1)%NUM_TAPS; //represents the next location of the sample to be stored, relative to pval
// sample_offset = (sample_offset < 0 ? NUM_TAPS -1 : sample_offset); //wrap around if the sample_offset goes negative
// MOD_MASK works faster than the above
sample_offset = (sample_offset - 1) & MOD_MASK;
}
}
At the end of the day I want to be able to refer to the newest sample as x[0] and the oldest sample as x[NUM_TAPS-1] (or equivalent).
Any way you implement this is very expensive, because each time you record a new sample, you have to move all the other samples (or pointers to them, or an equivalent). Pointers don't really help you here. In fact, using pointers as you do is probably a little more costly than just working directly with the buffer.
My suggestion would be to give up the idea of "remapping" indices persistently, and instead do it only virtually, as needed. I'd probably ease that and ensure it is done consistently by writing data access macros to use in place of direct access to the buffer. For example,
// expands to an expression designating the sample at the specified
// (virtual) index
#define SAMPLE(index) (val[((index) + sample_offset) % NUM_TAPS])
You would then use SAMPLE(n) instead of x[n] to read the samples.
I might consider also providing a macro for adding new samples, such as
// Updates sample_offset and records the given sample at the new offset
#define RECORD_SAMPLE(sample) do { \
sample_offset = (sample_offset + NUM_TAPS - 1) % NUM_TAPS; \
val[sample_offset] = sample; \
} while (0)
With regard to your specific questions:
Is there a better way to assign indexes than a conditional assignment (to wrap indexes < 0) with the modulus operator (to wrap
indexes > NUM_TAPS -1)? I can't think of a way that pointers to
pointers would help, but does anyone else have thoughts on this?
I would choose modulus over a conditional every time. Do, however, watch out for taking the modulus of a negative number (see above for an example of how to avoid doing so); such a computation may not mean what you think it means. For example -1 % 2 == -1, because C specifies that (a/b)*b + a%b == a for any a and b such that the quotient is representable.
Instead of shifting the data itself as in a FIFO to organize the values of x, I decided here to rotate the indexes. I would guess that
for data structures close to or smaller in size than the pointers
themselves that data moves might be the way to go but for very large
numbers (floats, etc.) perhaps the pointer assignment method is the
most efficient. Thoughts?
But your implementation does not rotate the indices. Instead, it shifts pointers. Not only is this about as expensive as shifting the data themselves, but it also adds the cost of indirection for access to the data.
Additionally, you seem to have the impression that pointer representations are small compared to representations of other built-in data types. This is rarely the case. Pointers are usually among the largest of a given C implementation's built-in data types. In any event, neither shifting around the data nor shifting around pointers is efficient.
Is the modulus operator generally considered close in speed to conditional statements? For example, which is generally faster?:
On modern machines, the modulus operator is much faster on average than a conditional whose result is difficult for the CPU to predict. CPUs these days have long instruction pipelines, and they perform branch prediction and corresponding speculative computation to enable them to keep these full when a conditional instruction is encountered, but when they discover that they have predicted incorrectly, they need to flush the whole pipeline and redo several computations. When that happens, it's a lot more expensive than a small number of unconditional arithmetical operations.
I am writing a program that reads wavelength and intensity data from separate signal and background files (so each file is comprised of a number of pairs of wavelength and intensity). As you can see, I do this by creating a structure, and then assigning the values to the proper elements in the structure using fscanf in a loop. Once the data is read in, the program is supposed to plot it on the interval where the recorded wavelengths in each file overlap, that is, the common range of wavelengths. The wavelengths align perfectly where this overlap exist and are known to be spaced at a constant difference. Thus, my way of discerning which elements of the structure array were applicable was to determine which of the two files' minimum wavelength was higher, and maximum wavelength was lower. Then, for the file that had the lower minimum and higher maximum, I would find the difference between this and the higher minimum/lower maximum, and then divide it by the constant step to determine how many elements to offset. This works, except when the math is done, the program returns a wrong answer that is completely inexplicable.
In the code below, I define the constant step as lambdastep by calculating the difference between wavelengths of one element and the element before it. With my sample data, it is .002, which is confirmed by printf. However, when I run the program and divide by lambdastep, I get an incorrect answer. When I run the program dividing by .002, I get the correct answer. Why is this case? There is no explanation I can think of.
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include "plots.h"
struct spectrum{
double lambda;
double intensity;
};
main(){
double a=0,b=0,c=0,d=0,lambdastep,smin,smax,bmin,bmax,tmin,tmax,sintmin,bintmin,tintmin,sintmax,bintmax,tintmax,ymin,ymax;
int ns,nb,nt,i=0,sminel,smaxel,bminel,bmaxel,tminel,tmaxel;
double min(struct spectrum *a,int,int);
double max(struct spectrum *a,int,int);
FILE *Input;
Input = fopen("sig.dat","r");
FILE *InputII;
InputII = fopen("bck.dat","r");
fscanf(Input,"%d",&ns);
fscanf(InputII,"%d",&nb);
struct spectrum signal[ns];
struct spectrum background[nb];
struct spectrum *s = &signal[0];
struct spectrum *ba = &background[0];
s = malloc(ns*sizeof(struct spectrum));
ba = malloc(nb*sizeof(struct spectrum));
while( fscanf(Input,"%lf%lf",&a,&b) != EOF){
signal[i].lambda = a;
signal[i].intensity = b;
i++;
}
i = 0;
while( fscanf(InputII,"%lf%lf",&c,&d) != EOF){
background[i].lambda = c;
background[i].intensity = d;
i++;
}
for (i=0; i < ns ;i++){
printf("%.7lf %.7lf\n", signal[i].lambda,signal[i].intensity);
}
printf("\n");
for (i=0; i < nb ;i++){
printf("%.7lf %.7lf\n", background[i].lambda,background[i].intensity);
}
lambdastep = signal[1].lambda - signal[0].lambda; //this is where I define lambdastep as the interval between two measurements
smin = signal[0].lambda;
smax = signal[ns-1].lambda;
bmin = background[0].lambda;
bmax = background[nb-1].lambda;
if (smin > bmin)
tmin = smin;
else
tmin = bmin;
if (smax > bmax)
tmax = bmax;
else
tmax = smax;
printf("%lf %lf %lf %lf %lf %lf %lf\n",lambdastep,smin,smax,bmin,bmax,tmin,tmax); //here is where I confirm that it is .002, which is the expected value
sminel = (tmin-smin)/(lambdastep); //sminel should be 27, but it returns 26 when lamdastep is used. it works right when .002 is directly entered , but not with lambdastep, even though i already confirmed they are exactly the same. why?
sminel is an integer, so (tmin-smin)/lambdastep will be casted to an integer when the calculation concludes.
A very slight difference in lambdastep could be the difference between getting e.g. 27.00001 and 26.99999; the latter truncates down to 26 when cast to an int.
Try using floor, ceil, or round to get better control over the rounding of the returned value.
It almost certainly has to do with the inherent imprecision of floating-point calculations. Trying printing out lambdastep to many significant digits -- I bet you'll find that its exact value is slightly larger than you think it is.
With my sample data, it is .002, which is confirmed by printf.
Try printing out (lambdastep == .002).
So I am trying to do this problem:
However, I'm not entirely sure where to start or what exactly I am looking for.
In addition, I was told I should expect to give the program inputs such as: zero (0), very small (0.00001), and not so small (0.1).
I was given this: http://en.wikipedia.org/wiki/E_%28mathematical_constant%29 as a reference, but that formula doesn't look exactly like the one in the problem.
And finally, I was told that the input to the program is a small number Epsilon. You may assume 0.00001f, for example.
You keep adding the infinite series until the current term's value is below the Epsilon.
But all in all, I have no clue what that means. I somewhat understand the equation on the wiki. However, I'm not sure where to start with the problem given. Looking at it, does anyone know what kind of formula I should be looking to use in C and what "E" is and where it comes into play here (i.e. within the formula, I understand it's suppose to be the user input).
Code So Far
#include <stdio.h>
#include <math.h>
//Program that takes in multiple dates and determines the earliest one
int main(void)
{
float e = 0;
float s = 0;
float ct = 1;
float ot= 1;
int n = 0;
float i = 0;
float den = 0;
int count = 0;
printf("Enter a value for E: ");
scanf("%f", &e);
printf("The value of e is: %f", e);
for(n = 0; ct > e; n++)
{
count++;
printf("The value of the current term is: %f", ct);
printf("In here %d\n", count);
den = 0;
for(i = n; i > 0; i--)
{
den *= i;
}
//If the old term is one (meaning the very first term), then just set that to the current term
if (ot= 1)
{
ct = ot - (1.0/den);
}
//If n is even, add the term as per the rules of the formula
else if (n%2 == 0)
{
ct = ot + (1.0/den);
ot = ct;
}
//Else if n is odd, subtract the term as per the rules of the formula
else
{
ct = ot - (1.0/den);
ot = ct;
}
//If the current term becomes less than epsilon (the user input), printout the value and break from the loop
if (ct < epsilon)
{
printf("%f is less than %f",ct ,e);
break;
}
}
return 0;
}
Current Output
Enter a value for E: .00001
The value of e is: 0.000010
The value of the current term is: 1.000000
In here 1
-1.#INF00 is less than 0.000010
So based on everyone's comments, and using the 4th "Derangements" equation from wikipedia like I was told, this is the code I've come up with. The logic in my head seems to be in line with what everyone has been saying. But the output is not at all what I am trying to achieve. Does anyone have any idea from looking at this code what I might be doing wrong?
Σ represents a sum, so your equation means to compute the sum of the terms starting at n=0 and going towards infinity:
The notation n! means "factorial" which is a product of the numbers one through n:
Each iteration computed more accurately represents the actual value. ε is an error term meaning that the iteration is changing by less than the ε amount.
To start computing an interation you need some starting conditions:
unsigned int n = 0; // Iteration. Start with n=0;
double fact = 1; // 0! = 1. Keep running product of iteration numbers for factorial.
double sum = 0; // Starting summation. Keep a running sum of terms.
double last; // Sum of previous iteration for computing e
double e; // epsilon value for deciding when done.
Then the algorithm is straightforward:
Store the previous sum.
Compute the next sum.
Update n and compute the next factorial.
Check if the difference in the new vs. old iteration exceeds epsilon.
The code:
do {
last = sum;
sum += 1/fact;
fact *= ++n;
} while(sum-last >= e);
You need to write a beginning C program. There are lots of sources on the interwebs for that, including how to get user input from the argc and argv variables. It looks like you are to use 0.00001f for epsilon if it is not entered. (Use that to get the program working before trying to get it to accept input.)
For computing the series, you will use a loop and some variables: sum, current_term, and n. In each loop iteration, compute the current_term using n, increment n, check if the current term is less than epsilon, and if not add the current_term to the sum.
The big pitfall to avoid here is computing integer division by mistake. For example, you will want to avoid expressions like 1/n. If you are going to use such an expression, use 1.0/n instead.
Well in fact this program is very similar to the ones given in the learning to Program in C by Deitel, well now to the point (the error can't be 0 cause e is a irrational number so it can't be calculated exactly) I have here a code that may be very useful for you.
#include <stdio.h>
/* Function Prototypes*/
long double eulerCalculator( float error, signed long int *iterations );
signed long int factorial( int j );
/* The main body of the program */
int main( void )
{
/*Variable declaration*/
float error;
signed long int iterations = 1;
printf( "Max Epsilon admited: " );
scanf( "%f", &error );
printf( "\n The Euler calculated is: %f\n", eulerCalculator( error, &iterations ) );
printf( "\n The last calculated fraction is: %f\n", factorial( iterations ) );
return 1;
}
long double eulerCalculator( float error, signed long int *iterations )
{
/* We declare the variables*/
long double n, ecalc;
/* We initialize result and e constant*/
ecalc = 1;
/* While the error is higher than than the calcualted different keep the loop */
do {
n = ( ( long double ) ( 1.0 / factorial( *iterations ) ) );
ecalc += n;
++*iterations;
} while ( error < n );
return ecalc;
}
signed long int factorial( signed long int j )
{
signed long int b = j - 1;
for (; b > 1; b--){
j *= b;
}
return j;
}
That summation symbol gives you a clue: you need a loop.
What's 0!? 1, of course. So your starting value for e is 1.
Next you'll write a loop for n from 1 to some larger value (infinity might suggest a while loop) where you calculate each successive term, see if its size exceeds your epsilon, and add it to the sum for e.
When your terms get smaller than your epsilon, stop the loop.
Don't worry about user input for now. Get your function working. Hard code an epsilon and see what happens when you change it. Leave the input for the last bit.
You'll need a good factorial function. (Not true - thanks to Mat for reminding me.)
Did you ask where the constant e comes from? And the series? The series is the Taylor series expansion for the exponential function. See any intro calculus text. And the constant e is simple the exponential function with exponent 1.
I've got a nice Java version working here, but I'm going to refrain from posting it. It looks just like the C function will, so I don't want to give it away.
UPDATE: Since you've shown yours, I'll show you mine:
package cruft;
/**
* MathConstant uses infinite series to calculate constants (e.g. Euler)
* #author Michael
* #link
* #since 10/7/12 12:24 PM
*/
public class MathConstant {
public static void main(String[] args) {
double epsilon = 1.0e-25;
System.out.println(String.format("e = %40.35f", e(epsilon)));
}
// value should be 2.71828182845904523536028747135266249775724709369995
// e = 2.718281828459045
public static double e(double epsilon) {
double euler = 1.0;
double term = 1.0;
int n = 1;
while (term > epsilon) {
term /= n++;
euler += term;
}
return euler;
}
}
But if you ever need a factorial function I'd recommend a table, memoization, and the gamma function over the naive student implementation. Google for those if you don't know what those are. Good luck.
Write a MAIN function and a FUNCTION to compute the approximate sum of the below series.
(n!)/(2n+1)! (from n=1 to infinity)
Within the MAIN function:
Read a variable EPSILON of type DOUBLE (desired accuracy) from
the standard input.
EPSILON is an extremely small positive number which is less than or equal to
to 10^(-6).
EPSILON value will be passed to the FUNCTION as an argument.
Within the FUNCTION:
In a do-while loop:
Continue adding up the terms until |Sn+1 - Sn| < EPSILON.
Sn is the sum of the first n-terms.
Sn+1 is the sum of the first (n+1)-terms.
When the desired accuracy EPSILON is reached print the SUM and the number
of TERMS added to the sum.
TEST the program with different EPSILON values (from 10^(-6) to 10^(-12))
one at a time.