Implementing two sample t-test in C - c

I am making a function that will calculate the test statistic from a two sample t-test and return it's value. However, I have been getting incorrect results. I previously was using scanf and got good answers, but it randomly stopped working. So I decided to switch to fgets which is suppose to be more reliable, however, the values it's returning are incorrect.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define VAL 10
double tstat(int x1,int x2,int s1,int s2,int n1,int n2);
int main()
{
char mean1[VAL] = {0};
char sd1[VAL] = {0};
char n1[VAL] = {0};
char mean2[VAL] = {0};
char sd2[VAL] = {0};
char n2[VAL] = {0};
printf("Enter mean 1: \n");
fgets(mean1, 10, stdin);
printf("Enter sd 1: \n");
fgets(sd1, 10, stdin);
printf("Enter sample size 1: \n");
fgets(n1, 10, stdin);
printf("Enter mean 2: \n");
fgets(mean2, 10, stdin);
printf("Enter sd 2: \n");
fgets(sd2, 10, stdin);
printf("Enter n2: \n");
fgets(n2, 10, stdin);
printf("t value is: %lf", tstat(atoi(mean1),atoi(mean2),atoi(sd1),atoi(sd2),atoi(n1),atoi(n2)));
}
double tstat(int x1,int x2,int s1,int s2,int n1,int n2)
{
double t = 0;
t = (x1 - x2)/(sqrt(pow(s1,2)/n1+pow(s2,2)/n2));
return t;
}
For example, setting mean1 = 1.3, sd1 = 0.5, n1 = 22; mean2 = 1.6,sd2 = 0.3, n2 = 24 should yield a value of -2.44, however, plugging this in returns -1 followed by #IND00. I presume my issue is that either I am misinterpreting how to properly use fgets, or something is going wonky with the datatypes, though I am a beginner in C, and I have not been able to spot any clear errors.

Your variables are all of type int and you're using atoi to convert the strings to int. However, the values you're entering aren't integers, they're floating point values, so only the integer part of each number is interpreted. For example, atoi("1.3") results in 1.
You need to change your datatypes to double and use atof instead.
double tstat(double x1, double x2, double s1, double s2, double n1, double n2)
{
double t = 0;
t = (x1 - x2)/(sqrt(pow(s1,2)/n1+pow(s2,2)/n2));
return t;
}
...
printf("t value is: %lf", tstat(atof(mean1),atof(mean2),atof(sd1),atof(sd2),atof(n1),atof(n2)));

Related

Not able to find my segmentation fault in this code of t-test

I have written this program for t-test. I'll add other functions as well, but first, I need to find my error. Here's my code
# include <stdio.h>
# include <math.h>
float mean(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += x[i];
return sum/size;
}
float sumsq(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += pow(x[i]-mean(x,size),2);
return sum;
}
int input(n)
{
float x[n];
printf("Enter the values one by one");
for (int i = 0; i<n;i++)
scanf("%f", &x[i]);
return x;
}
void t_check(float x)// Make sure to write this function before each of the t-tests. That is because it is of void type. If the t-test is done before the checking function is declared, then it assumes it's datatype to be "int", and we get an error. So either write the t-check function before those functions, or just define it at the beginning of the program
{
float t_tab;
printf("Enter the tabulated value of t");
scanf("%f",&t_tab);
if (x<t_tab)
printf("We do not have enough evidence to reject the null hypothesis");
else
printf("Reject the null hypothesis");
}
float t_diff_of_means()
{
float x=0.0,y=0.0,s1=0.0,s2=0.0,S=0.0,t=0.0,tcal;
int n,m,a,b;
printf("Enter the number of variables in population 1");
scanf("%d", &n);
a = input(n);
printf("Enter the number of variables in population 2");
scanf("%d", &m);
b = input(m);
x = mean(a,n);
y = mean(b,m);
s1 = sumsq(a, n);
s2 = sumsq(b, m);
S = sqrt((s1+s2)/(n+m-2));
t = (x-y)/(S*sqrt(1.0/n+1.0/m));
t_check(t);
}
int main(void)
{
t_diff_of_means();
return 0;
}
It gives segmentation fault as an error. I'm not able to understand where my code uses any memory uses a part of memory that is not allocated to it
The main issue is you expect input() to read an array floats but you return an int. You should declare the type of the argument n. You cannot return an address to a local variable as it out of scope for caller. The easiest option is to the declare the array variable in main() then pass it to input to populate (pun). (not fixed) Check that return value of scanf() otherwise the variable you expect to be initialized may not be.
t_diff_of_means() is declared to return a float but nothing is returned. Not sure what you want to return so I changed the return type to void.
Tweaked various prompts to make it more them more readable.
#include <stdio.h>
#include <math.h>
float mean(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += x[i];
return sum/size;
}
float sumsq(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += pow(x[i]-mean(x,size),2);
return sum;
}
void input(size_t n, float a[n])
{
printf("Enter the values one by one: ");
for (int i = 0; i<n;i++)
scanf("%f", a+i);
}
void t_check(float x)
{
float t_tab;
printf("Enter the tabulated value of t: ");
scanf("%f",&t_tab);
if (x<t_tab)
printf("We do not have enough evidence to reject the null hypothesis\n");
else
printf("Reject the null hypothesis\n");
}
void t_diff_of_means()
{
float x=0.0,y=0.0,s1=0.0,s2=0.0,S=0.0,t=0.0;
int n,m;
printf("Enter the number of variables in population 1: ");
scanf("%d", &n);
float a[n];
input(n, a);
printf("Enter the number of variables in population 2: ");
scanf("%d", &m);
float b[m];
input(m, b);
x = mean(a,n);
y = mean(b,m);
s1 = sumsq(a, n);
s2 = sumsq(b, m);
S = sqrt((s1+s2)/(n+m-2));
t = (x-y)/(S*sqrt(1.0/n+1.0/m));
t_check(t);
}
int main(void)
{
t_diff_of_means();
return 0;
}
and example run:
Enter the number of variables in population 1: 2
Enter the values one by one: 1
2
Enter the number of variables in population 2: 2
Enter the values one by one: 2
3
Enter the tabulated value of t: 0.05
We do not have enough evidence to reject the null hypothesis
Consider eliminating the variables you only use once (x, y, s1, s2, S, t and t_cal):
t_check(
(mean(a, n) - mean(b, m)) / (sqrt((sumsq(a, n)+sumsq(b, m))/(n+m-2))*sqrt(1.0/n+1.0/m))
);
then I observed that this only depends on variables a, n, b and m so push that calculation into t_check():
void t_check(size_t a_len, float a[a_len], size_t b_len, float b[b_len]) {
float t = (mean(a, a_len) - mean(b, b_len)) / (sqrt((sumsq(a, a_len)+sumsq(b, b_len))/(a_len+b_len-2))*sqrt(1.0/a_len+1.0/b_len));
// ...
}
Then I changed the length types to size_t and used the clearer variable names in t_diff_of_means():
void t_diff_of_means()
{
printf("Enter the number of variables in population 1: ");
size_t a_len;
scanf("%zu", &a_len);
float a[a_len];
input(a_len, a);
printf("Enter the number of variables in population 2: ");
size_t b_len;
scanf("%zu", &b_len);
float b[b_len];
input(b_len, b);
t_check(a_len, a, b_len, b);
}
We could take this another step by observing the two first sections in t_diff_of_means() are very similar, so we could have input() take a prompt and a pointer to an array of floats along with elements read. input() would then need to dynamically allocate the array of floats. This means most of our functions take a array of float and length argument. Let's create a type for that and refactor our functions to use it:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct array {
size_t len;
float *data;
};
float mean(struct array *a)
{
float sum = 0;
for (int i=0; i<a->len;i++)
sum += a->data[i];
return sum/a->len;
}
float sumsq(struct array *a)
{
float sum = 0;
for (int i=0; i<a->len;i++)
sum += pow(a->data[i] - mean(a), 2);
return sum;
}
void input(int prompt, struct array *a)
{
printf("Enter the number of variables in population %d: ", prompt);
scanf("%zu", &a->len);
a->data = malloc(a->len * sizeof(a->data[0]));
//if(!a->data) ...
printf("Enter the values one by one: ");
for (int i = 0; i<a->len;i++)
scanf("%f", &a->data[i]);
}
void t_check(struct array a[2])
{
float t = (mean(a) - mean(a+1)) / (
sqrt(
(sumsq(a) + sumsq(a+1)) / (a[0].len + a[1].len-2)
) * sqrt(1.0/a[0].len + 1.0/a[1].len)
);
printf("Enter the tabulated value of t: ");
float t_tab;
scanf("%f",&t_tab);
if (t<t_tab)
printf("We do not have enough evidence to reject the null hypothesis\n");
else
printf("Reject the null hypothesis\n");
}
int main(void)
{
struct array a[2];
input(1, a);
input(2, a+1);
t_check(a);
}
This would be a good base to add additional functions to.

C anomaly invalid output

I have code that needs to run some functions with arguments from stdin. First function counts factorial of argument, second one counts length and square of round with radius presented by argument. Third needs just to printf its arguments.But after my input I have very strange result. My IDE is Xcode
Input:
5
1.3
8
8
fgd
Expected output:
120
Obvod: 8.168134 Obsah: 5.309287
88fgd
Real output:
120
Obvod: 8.168134 Obsah: 5.309287
88
fg
Whats wrong with last input? Thanks a lot in advance for your answer! The whole code below:
#include <stdio.h>
#include <stdlib.h>
int factorial (int value)
{
int fac = value;
if (value == 0)
{
return 1;
}
else if (value < 0)
{
return 0;
}
for (int i = 1; i < value; i++)
{
fac *= value - i;
}
return fac;
}
void radius (float rad, float* lep, float* sqp)
{
const float pi = 3.14159;
if (rad < 0)
{
printf("Obvod: 0 Obsah: 0\n");
}
float lenght = 2 * pi * rad;
float square = pi * (rad * rad);
*lep = lenght;
*sqp = square;
printf("Obvod: %f Obsah: %f\n", lenght, square);
}
void read_array_data(int h, int w, char x1, char x2, char x3)
{
printf("%i%i%c%c%c\n", h, w, x1, x2, x3);
}
int main()
{
char c1;
char c2;
char c3;
int f, height, width;
float r;
float radius_container, square_container;
float* p1 = &radius_container;
float* p2 = &square_container;
scanf("%i", &f);
scanf("%f", &r);
scanf("%i", &height);
scanf("%i", &width);
scanf("%c%c%c", &c1, &c2, &c3);
printf("%i\n", factorial(f));
radius(r, p1, p2);
read_array_data(height, width, c1, c2, c3);
}
scanf(" %c%c%c", &c1, &c2, &c3);
// ^^^ insert space here
When you hit Enter from the previous scanf, a newline is left in stdin. That newline is read into c1, the f into c2, and finally g into c3. When you print, the newline prints dropping to the next line, followed by fg. The leading space tells scanf to skip that leading whitespace. After that, the fgd characters will be read into c1, c2, c3 as you expect.
Demonstration
See scanf("%c") call seems to be skipped for more info

Error "too few arguments to function call, at least argument 'format' must be specified" C programming

#include <cs50.h>
//declare functions
int add_two_ints(int a, int b);
int main(void)
{
//ask the user for input
printf("give an integer: ");
int x = get_int();
printf("give me another integer: ");
int y = get_int();
//call function
int z = add_two_ints(x, y);
printf("the result of %i plus %i is %i!\n", x, y, z);
}
//function
int add_two_ints(int a, int b)
{
int sum = a + b;
return sum;
}
when i run the program i get the error too few arguments to function call, at least argument format must be specified
this is a simple function with only two arguments being pass since im new to c programming im trying to figure out where i made the mistake.
whats is the correct way to write function ?
The get_int function included as part of CS50 expects a string for a prompt, which you're not passing. So instead of this:
printf("give an integer: ");
int x = get_int();
You want this:
int x = get_int("give an integer: ");
And similarly for reading y.
I just realize what I was doing wrong the get_int was expecting a string so I just deleted the printf statement and put in on to the get_int so now when it runs it works
#include <stdio.h>
#include <cs50.h>
//declare functions
int add_two_ints(int a, int b);
int main(void)
{
//ask the user for input
int x = get_int("give an integer: ");
int y = get_int("give an integer: ");
int z = add_two_ints(x, y);
printf("the result of %i plus %i is %i!\n", x, y, z);
}
int add_two_ints(int a, int b)
{
int sum = a + b;
return sum;
}

Square root not diving properly

I've created a program which takes an integer x input, then loops until x is met while also taking other integer inputs. I then do various calculations, and then find a square root of a certain value. When I divide by square root however I get a 0 when I know I should be getting a different value as the maths doesn't add up.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main(void) {
int multiply1, multiply2, add, squareRoot;
int i;
int n;
int x;
int s;
double divide, test = 0;
scanf("%d", &x);
for (s = 0; s < x; s++) {
scanf("%d %d", &i ,&n);
}
multiply1 = i * i;
multiply2 = n * n;
add = multiply1 + multiply2;
squareRoot = sqrt(add);
printf("%d", i);
test = (i / squareRoot);
printf("Multiplication = %d\n", multiply1);
printf("Multiplication = %d\n", multiply2);
printf("Added together = %d\n", add);
printf("square root = %d\n", squareRoot);
printf("First output = %.3f\n", test);
return 0;
}
You are dividing two integers so the actual division returns the result rounded down. You should instead cast to double and then divide.
test = ((double)i/squareRoot);
There are two things you can do,
Without changing your program, simply cast the i and squareRoot variables to double
test = (double) i / (double) squareRoot;
Change your program and make i and squareRoot a double.
I, would choose 2 because sqrt() returns a double and that might cause an integer overflow.

How to multiplying, multiple inputs from using while loop in c

I have to multiply digits by taking input from the user and when he enter 'n' it will produce the answer.
For example (2*3*2 = 12). But I manage to write the code for taking two inputs but can't find the way to take multiple inputs from user and produce the total answer. Here is the code;
void main (void)
{
float f1,f2;
float total;
int status1,status2;
printf("Enter first number to multiply:'n' to quit.\n ");
status1=scanf("%f",&f1);
printf("Enter another number to be multiply:'n' to quit.\n ");
status2=scanf("%f",&f2);
while (status1==1 && status2==1)
{
total=f1*f2;
status1=scanf("%1.0f",&f1);
status2=scanf("%1.0f",&f2);
}
printf("Multiplition Total = %1.0f",total);
getch();
}
You can use a while loop, as follows.
float prod = 1, f;
printf( "Enter the numbers, n to stop.\n" );
while( scanf( "%f", &f ) )
prod *= f;
printf( "product = %f\n", prod );
Tested:
#include <stdio.h>
int main()
{
int total = 1, factor = 1, success;
do
{
total *= factor;
printf("Enter integer number to multiply or 'n' to quit: ");
success = scanf("%d", &factor);
}
while (success);
printf("Multiplication Total = %d\n", total);
return 0;
}
And a piece of advice as you said you start your adventure with C:
Unless you have some specific reason to do otherwise, use double, not float.
However, in your question you asked for digits (integer) multiplication, so int is sufficient. If you can avoid floating point numbers, avoid them. They're much more complicated then integers and can let you in worse problems if you don't use them with caution.
You can refer to What Every Computer Scientist Should Know About Floating-Point Arithmetic.
This would do what you need and handles, 0, 1 or an unlimited number of inputs:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
float f1;
float total = 0;
printf("Enter number: ");
if (scanf("%f",&total))
{
for (;;)
{
printf("Enter number: ");
if (!scanf("%f", &f1))
{
break;
}
total *= f1;
}
}
printf("Multiplication Total = %f\n",total);
getch();
return 0;
}
It keeps a running total as values are entered but it stops on first invalid input, not just when n is entered.
Untested:
float f, p = 1;
printf ("Enter a number: ");
fflush (stdout);
while (scanf("%f", &f) != EOF)
{
p *= f;
printf ("Enter another number: ");
fflush (stdout);
}
printf ("Product: %f\n", p);

Resources