I tried everything to get standard deviation to work.
I'm trying to make a program that gets grades of students (count decided by user) and it calculates the mean of the grades and also the standard deviation. It calculates the mean fine but for standard deviation it gives "7712160851427328.00"
#include <stdio.h>
int main(){
int i;
int j;
int count;
int grade = 0;
int grades[5] = {0}; //Init
int sum = 0;
float deviation_sum;
float mean;
float standard_deviation;
printf("Give Count: ");
scanf("%d", &count);
for(i = 0; i < count; i++){
printf("Give %d grade: ", (i+1));
scanf("%d", &grade);
switch(grade){
case 0:
grades[0]++;
break;
case 1:
grades[1]++;
break;
case 2:
grades[2]++;
break;
case 3:
grades[3]++;
break;
case 4:
grades[4]++;
break;
case 5:
grades[5]++;
}
sum += grade;
}
mean = sum/count;
printf("mean: %.2f \n", mean);
for(i = 0; i <= 5; i++){
while(grades[i] == 0){
i++;
}
for(j = 0; j < grades[i]; j++){
deviation_sum += (i-mean)*(i-mean);
printf("%d,%d\n",i,j);
}
}
standard_deviation = sqrt(deviation_sum /count - 1);
printf("deviation: %.2f\n", standard_deviation);
}
I think the problem is in the last for loop just can't figure it out.
You'll have to initilize deviation_sum to zero. Otherwise it takes garbage value as its initial value
Your mean calculation will fail as you are doing integer division, and this will then make the subsequent std dev calculation incorrect.
Change:
mean = sum/count;
to
mean = (float)sum/count;
so that the division is performed using floating point arithmetic. You might also want to print the value of mean at this point to check that it looks reasonable.
Also this
standard_deviation = sqrt(deviation_sum /count - 1);
shall be
standard_deviation = sqrt(deviation_sum / (count - 1));
Please see here for the background.
First of all, avoid this type of construct (i could cause array access out-of-bounds):
for(i = 0; i <= 5; i++){
while(grades[i] == 0){
i++;
}
Use if instead of while and use continue to loop over again.
For correcting the error you are getting, do following changes in your code (I am just giving you hints)
1. Use typecasting where necessary
2. Monitor variables (especially array indices) for proper bounds
3. When using functions like sqrt, do check for positivity of the argument otherwise you may face Domain ERROR.
4. Always remember to initialize variables when required.
I would also suggest a task for you:
Try removing your switch with a simpler logic.
Related
I wrote some code that reads numbers from another file and it's supposed to input the numbers from the file and output the average. The numbers I input are (1,2,3,4,5,6,7,8,9,10). But the average it's giving me is 2,4,6,8.10.
How do I correct this?
Code:
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *myFile;
myFile = fopen("numbers.txt", "r");
int numberArray[10];
int i;
int sum = 0;
int n = 0;
int avg = 0;
if (myFile == NULL){
printf("Error Reading File\n");
exit (0);
}
for (i = 0; i < 10; i++){
fscanf(myFile, "%d,", &numberArray[i] );
}
for (i = 0; i < 10; i++){
sum += n;
i++;
avg = (sum / i);
printf("Average is: %d\n\n", numberArray[i]);
}
fclose(myFile);
return 0;
}
"...The numbers I input are (1,2,3,4,5,6,7,8,9,10) Instead of the average its giving me 2,4,6,8.10. How do I correct this?..."
Focusing on only the final loop, a few items to consider that will address this issue, and a few others:
Depending on values of numerator and divisor the average might not be exactly correct due to integer division rounding error. if this is an issue for you, the first code snippet addresses it. If not, the following snippets address only the skipping array elements...
As covered, the following code segment in the original post increments i twice, once in the for() loop, then later in the i++ statement. The following addresses each of these, also corrects assignment statements, all with with comments...
float sum = 0.0;//to avoid integer division rounding error, use a floating point type
float ave = 0.0;
for (i = 0; i < 10; i++){
//sum += n;//n does not represent the values strore
sum += (float)numberArray[i];
//i++;//not needed, i is incremented in for loop
avg = (sum/i);
printf("Average is: %f\n\n", ave);
// ^ changed from d to f,
// and numberArray[i] to ave
}
Note, if the effects of integer division are acceptable for your purposes, then use the following:
int sum = 0;
int ave = 0;
for (i = 0; i < 10; i++){
sum += numberArray[i];
avg = (sum/i);
printf("Average is: %d\n\n", ave);
}
And, if outputting only the final result is required (rather than all of the intermediate values), move the last two statements to just after the for loop:
for (i = 0; i < 10; i++){
sum += numberArray[i];
}
avg = (sum/i);
printf("Average is: %d\n\n", ave);
"Is it possible to place the given average back into the file? "
The original statement: myFile = fopen("numbers.txt", "r"); opened the file for read only. But placing the resulting average back into the file requires reopening the file for append and using fputs():
...
fclose(myFile);
//add the following...
char sAve[20] = {0};
myFile = fopen("numbers.txt", "a");
if(myFile)
{
sprintf(sAve, "\nAverage is: %f0.6", ave)
fputs(sAve, myFile);
fclose(myFile);
}
return 0;
}
In this for loop, you increment i twice, once inside the for()-statement, once at i++.
for (i = 0; i < 10; i++){
sum += n;
i++;
avg = (sum/ i);
printf("Average is: %d\n\n", numberArray[i]);
}
If I understand correctly, the second increment should be removed. Also your intended output is not quite clear to me. If this does not solve it, maybe specify your question.
If you just want the average of all the numbers first add them all together:
for(i=0; i<10; i++){
sum+=numberArray[i];
}
Then divide by the number of elements
avg = sum/10;
Then you can printout the average:
printf("Average is: %d\n", avg);
I think this is what your code intends to do.
This is my first post on stack overflow, so this is my code so far, i'm just starting computer engineering and am having some trouble.
#include <stdio.h>
int main ( void ) {
int num, sum = 0, i, ssq = 0, isq, n;
printf("Enter an integer: ");
scanf("%d", &num);
for (i = 1; i <= num; i++) {
sum = sum + (i * i);
}
printf("The sum of the squares of integers from 0 to %d is %d\n", num, sum);
while (i >= 0) {
printf("Would you like to go again? (1 for yes, 0 for no): ");
scanf("%d", &i);
printf("Enter an integer: ");
scanf("%d", &num);
for (isq = 1; isq <= n; isq++);
ssq = ssq + (isq * isq);
printf("The sum of the squares of integers from 0 to %d is %d\n", num, sum);
if (i == 0) break;
}
return 0;
}
This is what I have so far believe it or not it took me 12 hours to do the first part, I've literally been up all night working on this, before the while loop and now I'm completely lost. I added the ssq=0, isq, and n ints in to try to help with no avail. At this point I'm just rearranging stuff for hours on end, this is my first post so please don't be too hard on me!
This contains a whole host of errors, from typos to code duplication, as #HappyCoder has noted above.
First of all, the outer part and the loop part do exactly the same. Think about it for a moment. You first do some task, unconditionally, then ask the user if they want to start over. The task itself doesn't change! Hence, what we can do is this:
do the task;
ask the user if they want to quit or go on;
if yes, return to the start.
In code, this can be done with an endless loop that you break out of if the user wants to stop:
while(1) {
// do user input and calculations here;
printf("Would you like to go again? (1 for yes, 0 for no): ");
scanf("%d", &i);
if (i == 0)
break;
}
See, now we only have one instance of the calculation code! Now, you can throw away half the variables declared in the beginning, since they are duplicate.
Now on to the calculations. You have an uninitialized variable, ssq, in the loop. See where code duplication can get you. In the outer part, it is initialized properly. Inside the loop, however, it is not guaranteed to hold any concrete value, most likely it contains garbage.
Also, as noted by #JohnHascall, this subtle error introduced most likely by a typo:
for (isq = 1; isq <= n; isq++); // <---- the evil semicolon
ssq = ssq + (isq * isq);
The semicolon after the for loop makes the loop empty, and the summation only happens once, but not in the loop, as you want it to be.
Then, you output (print) sum not ssq inside the loop, which is obviously not what you want to print. And, you use the uninitialized n variable from outside the loop as the boundary, instead of the user inputted num.
I want to add yet one more. Sanely naming the variables is a big deal as it helps you to catch potential errors and keep track of how variables are being used throughout the code, not to mention easier understanding of the code by others. Look: int i -> int choice better isn't it?
So we can rewrite the code like this:
#include <stdio.h>
int main ( void )
{
int boundary, choice, isq, ssq;
while (1) {
printf("Enter an integer: ");
scanf("%d", &boundary);
ssq = 0;
for (isq = 1; isq <= boundary; isq++) {
ssq = ssq + (isq * isq);
}
printf("The sum of the squares of integers from 0 to %d is %d\n", boundary, ssq);
printf("Would you like to go again? (1 for yes, 0 for no): ");
scanf("%d", &choice);
if (choice == 0)
break;
}
return 0;
}
for (isq=1; isq<=n; isq++);
ssq = ssq + (isq*isq);
The problem here is that 'n' is not initialized and not used in above scanf statement, you need to use 'num' instead of 'n'
for (isq=1; isq<=num; isq++)
ssq = ssq + (isq*isq);
One likely problem is here:
for (isq = 1; isq <= n; isq++);
ssq = ssq + (isq * isq);
You probably want:
for (isq = 1; isq <= n; isq++) {
ssq = ssq + (isq * isq);
}
Also, you should add:
ssq = 0;
above that loop (think about your 2nd trip through the loop).
Here is #iksemyonov 's answer refactored to honor the "no more than 7 lines in a method" rule (using a hard and fast arbitrary number like 7 is absurd, but the principle of making function do a specific understandable task is reasonable).
#include <stdio.h>
static int getBoundary ( void ) {
int boundary;
printf("Enter an integer: ");
scanf("%d", &boundary);
return boundary;
}
static int computeSSQ ( int limit ) {
int ssq = 0;
for (; limit > 0; --limit) ssq += (limit*limit);
return ssq;
}
static int again ( void ) {
int choice;
printf("Would you like to go again? (1 for yes, 0 for no): ");
scanf("%d", &choice);
return choice;
}
int main ( void ) {
do {
int boundary = getBoundary();
int ssq = computeSSQ(boundary);
printf("The sum of the squares of integers from 0 to %d is %d\n",
boundary, ssq);
} while (again());
return 0;
}
You have made a few mistakes here:
You have put a semicolon after the for loop inside the while block which should be removed.
Inside the while block you have accepted value for 'num' while you have used 'n' in the for loop (for which value is uninitialized). So you should accept the value of 'n' instead of 'num' or else replace 'n' in the for loop with 'num'.
If you want to exit the while loop immediately after user inputs 0 then move the if (i == 0) break; statement to below the scanf ("%d", &i) statement.
In the printf() statement next to the for loop, you have used value of 'sum' while you have calculated value for ssq.
Also you should write ssq = 0 after the printf() statement to reset its value to 0.
Correct all these and the program will work.
what you want to do was basically a menu driven program... i would suggest , like the above one's are right too... but another way you can do is using do{
//the task , i.e. the sum
} while(i!=0);
doing this since do while is an exit controlled loop as you might be knowing... so as in earlier stages u can be free from using break; keyword...
also as you are starting an early bird tip i would like to give is that the suggestion of using functions by #John above ....is good but not if you are doing mistakes in a normal int main() 15 lines code... since if you go in user defined functions like stated above you might go wrong in passing the arguments or basics of function passing... so go for a normal int main code for now...
Note i didnt meant that what # John said was wrong or something...just gave my view/advice
So I'm trying to solve this http://www.codeabbey.com/index/task_view/sum-in-loop and I have 45 random numbers to input. I'm coding using C so I want to use the scanf function. The problem is that since it's 45 numbers (which are separated by spaces) what I want to do is copy paste the values so that the program can solve them from an array. Should I do it like this:
int x [45];
scanf("%d %d....(x42) %d",&x,&x,...(x42),&x);
or is there a more efficient way of doing this? (I hope there is T_T)
You need not (and you should not) write a single format string containing 45(or whatever) format specifier, following 45 pointers.
You need to use a loop.
Example:
for loop with an array, will hold the supplied operands, too
int x[45] = {0};
int sum = 0;
for (int i = 0; i < 45; i++) //style supported over C99
{
scanf("%d", &x[i]);
sum += x[i];
}
printf("sum = %d\n", sum);
for loop without an array, won't hold the operands, only result
int x = 0;
int sum = 0;
for (int i = 0; i < 45; i++) //style supported over C99
{
scanf("%d", &x);
sum += x;
}
printf("sum = %d\n", sum);
I have write a program that allows me to firstly enter a character c followed by an integer n and n float values representing grades. Using array to store the grades I have entered and no more than 100 grades can be introduced. The program allowed me to calculate the sum of the elements in array when I enter 's', compute the production of the elements in array when i enter 'p' and compute the average of the element s when i enter other words. After i enter the grades and character. The program has no response when i hit return to continue. So where is the mistake in my code
#include<stdio.h>
#include<stdio.h>
int main()
{
char c;
int integer_grade [100];
float floting_grade [100];
printf("Enter a grade");
scanf("%i,%f",&integer_grade[100],&floting_grade[100]);
int *a;
a=&integer_grade[100];
int *b;
b=&floting_grade[100];
printf("Enter a character");
getchar();
scanf("%c",&c);
int n;
switch(c)
{
case 's':
for (n=0;n=100;n++)
*a+=*a;
*b+=*b;
printf("Sum is %d",*a+*b);
case 'p':
for (n=0;n=100;n++)
*a*=*a;
*b*=*b;
printf("Sum is %d",*a**b);
default:
for (n=0;n=100;n++)
*a+=*a;
*b+=*b;
printf("average is %d",(*a+*b)/100);
}
return 0;
}
The task is:
Write a program where you first enter a character c followed by an integer n and n float values representing grades. Use an array for storing the grades. You can assume that not more than 100 grades would be introduced. Yours program should compute and print the following: if c is 's' the sum of the grades, if c is 'p' the product of all grades and if another character was introduced then the arithmetic mean of all grades.
*use switch
*you can safely assume thee input will be valid.
Thoughts.
This is undefined behavior. You are assigning the read integer and float to offset 100 in those arrays, which doesn't exist.
int integer_grade[100];
float floting_grade[100];
scanf("%i,%f", &integer_grade[100], &floting_grade[100]);
These pointers point to memory that is outside the bounds of their respective arrays.
int *a = &integer_grade[100];
int *b = &floting_grade[100];
You ask for a character and then you ignore the value of that character:
getchar();
You then follow that up by getting the following character. Which is odd. But you do use the correct type and what not. So that's a win.
scanf("%c",&c);
Your indentation in these for loops implies that you think that both statements will be iterated on as part of the loop. That's incorrect. Use { ... } to accomplish that:
for (n=0;n=100;n++)
*a+=*a;
*b+=*b;
I have no idea what you think you're accomplishing by *a += *a. I do know that the value at *a is going to grow quite quickly (and will likely overflow).
Switch statements use fallthrough on the cases. That means that if your case is 's', it will run all of the code in the switch statement, including all three cases. If you don't want this behavior, you should place break statements at the end of each case.
Please go back to your book / faculty / internet resource and read how a for loop works. This doesn't do what you probably think it does. In fact, this is an infinite loop!
for (n=0; n=100; n++)
Whatever do you try to do here, it's not right at all.
First: You declare 2 arrays of 100 elements, THEN you assign values outside of that array bounds (100 element array start from 0, finishes at 99)
Second: You create 2 pointers that points to outside of those array bounds.
Third: Inside the switch , the for (n=0;n=100;n++) is wrong, it should be something like for(n = 0; n < 100; n++)
Fourth: This
for (n=0;n=100;n++)
*a+=*a;
*b+=*b;
it would increment (if that for would be correct) only the first statement.
Correct way would be
for (n = 0; n < 100; n++)
{
*a += *a;
*b += *b;
}
Proper code would be
#include <stdio.h>
int main()
{
char c;
int integer_grade[100];
float floting_grade[100];
int nr_of_grades;
int i = 0;
printf("Enter number of grades: ");
scanf("%d", &nr_of_grades);
for(i = 0; i < nr_of_grades; i++)
{
printf("Enter a int grade: ");
scanf("%d", &integer_grade[i]);
printf("Enter a float grade: ");
scanf("%f", &floting_grade[i]);
}
int operation_i = 0;
float operation_f = 0;
printf("Enter a character");
scanf(" %c", &c);
int n;
switch(c)
{
case 's':
for (n = 0; n < nr_of_grades; n++)
{
operation_i += integer_grade[n];
operation_f += floting_grade[n];
}
printf("Sums are Int: %d Float: %f", operation_i, operation_f);
case 'p':
operation_i = 1;
operation_f = 1;
for (n = 0; n < nr_of_grades; n++)
{
operation_i *= integer_grade[n];
operation_f *= floting_grade[n];
}
printf("Products are Int: %d Float: %f", operation_i, operation_f);
default:
for (n = 0; n < nr_of_grades; n++)
{
operation_i += integer_grade[n];
operation_f += floting_grade[n];
}
printf("Average is Int: %d Float: %f", operation_i / nr_of_grades, operation_f / nr_of_grades);
}
return 0;
}
i'm learning C.
i'm using ubuntu and have Code::Blocks as IDE
i have this code:
#include <stdio.h>
int rev (int num);
int main (){
int numb = 0;
printf("%d\n\n", numb);
printf("Please enter a number. Enter 9999 to stop\n");
scanf("%d", &numb);
printf("there?");
printf("%d\n", numb);
while (numb != 9999){
printf("The reversed number is %d\n", rev(numb));
printf("Please enter a number. Enter 9999 to stop\n");
scanf("%d", &numb);
} /* end of while */
}
int rev (int num){
printf("here?");
int total = 0;
long max = 10;
long max_const = 10;
printf("here");
for (max; max < num; max *= 10);
printf("%ld", max);
max_const = max;
for (int i = 0; i <= max_const; i *= 10, max /= 10){
total += num / max * i;
} /* end for */
return total;
}
I'm doing it in this way cause my book isn't clear...however, the problem is that it raise a Floating Point exception, in scanf...i'm typing normal numbers... the strange thing is that if i type everything but 9999, the program crash. if i type 9999, it prints 'there?' (so scanf it's ok) and stop later, obviously. why?
Thank you.
The two existing (be sure to return the result in rev, and put \n on the ends of printfs to be sure they make it through the buffer) answers are good points, but not the thing that's actually triggering your floating point exception. Try running it in a debugger, and you'll see that your algorithm is bad: eventually max becomes zero and you divide by it. I'll leave fixing that as an exercise for the reader; the problem isn't anything to do with scanf.
Your rev function needs to return the reversed number.