Recursion function; "...has stopped working" - c

I am trying to make a program that gives a specific sum until some point that I define, here it is:
float sum(int n,float m);
main(void) {
float a,m=1.0;
int n;
scanf_s("%ld", &n);
a = sum(n, m);
printf("%f", a);
}
float sum(int n, float m) {
if ((n/m) < 0.0005) {
return 0;
}
else {
return n/m + sum(n, m + 2);
}
}
(Notice that the point I defined is 0.0005) When I give a value bigger or equal to 5, program gives me this error:
...has stopped working
Also, when I increase the defined point to like 0.5, the number of values I can give increases too. Why do you think is this happening and how can I fix it?

The %ld format specifier to scanf_s expects a long int * argument. What you're passing in is a int *. These types are incompatible. Using the wrong format specifier invokes undefined behavior, which in this case manifests as a crash.
The proper format specifier for an int * is %d:
scanf_s("%d", &n);
EDIT:
The crash you're seeing is probably a stack overflow. The sum function will recursively call itself 1000 * n times. I see a similar error under MSVC but at a different limit. You can get around this by going with an iterative solution:
float sum(int n, float m){
float result = 0;
while ((n/m) >= 0.0005){
result += n/m;
m+=2;
}
return result;
}

Related

Weird bug in C: Different results to the same function sometimes right sometimes wrong

So I am trying to run this code where I calculate the mean and median in 2 functions. When I use these functions in my main function and run my program, sometimes it gives me the right answer and sometimes it gives me some random numbers for the mean even though I run the exact same code. Can somebody explain this behavior to me?
Any help is appreciated.
float mean(int *numbers, int n){
int i=0;
float solution;
float tmp_m;
for(i=0; i<n; i++){
tmp_m=(float)numbers[i]+tmp_m;
}
solution=tmp_m/((float)n);
return solution;
}
float median(int *numbers, int n){
float median;
float median_b;
int index;
int index_b;
if(n % 2 == 1){
index=n/2;
median= (float)numbers[index];
return median;
}else if (n % 2 == 0){
index_b=n/2;
float tmp_median;
tmp_median= (float)numbers[index_b] + (float)numbers[index_b-1];
median_b=tmp_median/((float)2);
return median_b;
}
}
#include <stdio.h>
int main () {
int array[6]={0,2,3,4,0,5};
int n=6;
float result=mean(array, n);
float result_median=median(array, n);
printf("%f\n%f\n", result, result_median);
return 0;
}
The variable tmp_m is left uninitialized and it gives you random values.
So, replace float tmp_m; with float tmp_m = 0; in the mean function.
You haven’t initialised tmp_m to zero before using it.
Your tmp_m is not initialized to 0, so it starts out as a random number, which results in an incorrect result

signal: segmentation fault (core dumped) error

Wrote a program that multiply two arrays like this:
uv = u1v1 + u2v2 + u3v3 + ... un*vn
after getting from the user both of the arrays, i get a "signal: segmentation fault (core dumped)" error.
here's the code:
#include <stdio.h>
int scalar_product(int vectorU[], int vectorV[], int vectorLength) {
int i, sum = 0;
for (i = 0; i < vectorLength; i++)
sum += (vectorU[i] * vectorV[i]);
return sum;
}
void userInterface() {
int vectorLength = 0, i;
printf("Please enter the length of the vectors: ");
scanf("%d", &vectorLength);
int vectorU[vectorLength], vectorV[vectorLength];
printf("\nVector U:");
for (i = 0; i < vectorLength; i++) {
printf("\n%d) ", (i + 1));
scanf("%d", &vectorU[i]);
}
printf("\nVector V:");
for (i = 0; i < vectorLength; i++) {
printf("\n%d) ", (i + 1));
scanf("%d", &vectorV[i]);
}
printf(scalar_product(vectorU, vectorV, vectorLength));
}
main(void) {
userInterface();
}
This call of printf is incorrect
printf(scalar_product(vectorU, vectorV, vectorLength));
You need to write at least
printf( "%d\n", scalar_product(vectorU, vectorV, vectorLength));
Also it would be better to declare and define the function like
long long int scalar_product( const int vectorU[], const int vectorV[], int vectorLength) {
long long int sum = 0;
for ( int i = 0; i < vectorLength; i++)
sum += ( long long int )vectorU[i] * vectorV[i];
return sum;
}
To output the result you need to use the format string "%lld\n"..
The type long long int is used to avoid an overflow.
Another way is to declare the function return type as double.
Also you forgot to specify the return type int of the function main.
Here:
printf(scalar_product(vectorU, vectorV, vectorLength));
... you have failed to specify a format for printf. As a result, it attempts to interpret the result of scalar_product() as a pointer to the format string. Undefined behavior results.
If your compiler is not emitting a warning about that then you should either learn how to turn up the warning level so that it does, or else get a better compiler. If your compiler is emitting a warning about it, then take this as a lesson that it is not safe to ignore compiler warnings.
Probably you wanted somethign more like this:
printf("%d\n", scalar_product(vectorU, vectorV, vectorLength));
As a minor additional issue, you have forgotten the return type for main(). Your compiler is probably treating it as returning int, which turns out to be the right thing to do, but that doesn't make your code correct. You want:
int main(void) {
// ...
With those two changes, your program compiles for me without any diagnostics, and runs without error, producing the result I expect.
At least, for small vector lengths. If you try really large vectors then you might exceed the available space for allocating your vectors on the stack.

Casting float to int doesn't work properly in C

I tried to solve a task on codewars and happened something strange, in one case casting worked as usual and in the second o got strange behavior. Here is the code:
#include <stdio.h>
#include <string.h>
#include <math.h>
int digital_root(int n) {
char tmp[30];
char *ptr;
while(n > 9){
sprintf(tmp, "%d", n);
int len = strlen(tmp);
float n_tmp = n / (pow(10, len));
n = 0;
for(int i = 1; i <=len; i++){
float t = n_tmp * (pow(10, i));
printf(" vars = [%f , %d] ", t, (int)t); //this line
n += (int) t;
n_tmp -= (int)t/pow(10,i);
}
}
return n;
}
int main()
{
digital_root(16);
return 0;
}
And the line printf(" vars = [%f , %d] ", t, (int)t); outputs: vars = [1.600000 , 1] vars = [6.000000 , 5], what is so strange. Can someone explain this behavior?
Every casting float to int is a rounding, so every time you do it, stop for a second and think: what kind of rounding do I need this time? Dropping the fractional part? floor()? ceil()? Or rounding positive float towards nearest int? If 5.999999999999 should be 6, use (int)(t+.5), not (int)t.
Or you can mimic the printf behavior and round only the smallest float fraction, which can vary (depending on the biggest value you use). (int)(t+.000001) will round both 1.9 to 1 (as it probably should), and 3.9999999999 to 4 (because it is 4 with some tiny number representation errors).
You should however know the size of a fraction which can be an actual, meaningful part of your data. Everything smaller than this fraction must be rounded. It can be either .00000001 or .5, that depends on your needs and the algorithm itself.

EQUATION SOLVER absurd result despite correct algorithm

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void bisect(float *p,int n,int a);
float value(float *p,int n,int a);
int main()
{
int a,i;
float *p;
printf("enter the degree of the polynomial\n");
scanf("%d",&a);
p=(float *) malloc(a*sizeof(float));
for(i=0;i<=a;i++)
{
printf("enter the coefficient of x^%d\n",i);
scanf("%f",p+i);
}
printf("%f\n",value(p,-2,a));
printf("%f\n",value(p,1,a));
printf("%f\n",value(p,0,a));
for(i=-100;i<100;i++)
{
if(value(p,i,a)*value(p,i+1,a)==0.000)
{
printf("%d\n",value(p,i+1,a));
if(value(p,i,a)==0&&value(p,i+1,a)==0.00)
{
printf("the roots are %d,%d\n",i,i+1);
}
if(value(p,i+1,a)==0.0)
{
printf("the real root is %d\n",i+1);
i++;
continue;
}
}
if(value(p,i,a)*value(p,i+1,a)<0)
{
bisect(p,i,a);
}
}
return 0;
}
float value(float *p,int n,int a)
{
float sum=0.0;
int i;
for(i=0;i<=a;i++)
{
sum=sum+*(p+i)*pow(n,i);
}
return sum;
}
void bisect(float *p,int n,int a)
{
float j,k,l;
int i;
j=n;k=n+1;l=(j+k)/2;
for(i=0;i<50;i++)
{
if(value(p,j,a)*value(p,l,a)==0){break;}
if(value(p,j,a)*value(p,l,a)<0)
{
j=j;k=l;l=(j+k)/2;
}
else if(value(p,l,a)*value(p,k,a)<0)
{
l=(l+k)/2;j=l;
}
}
printf("the root of the equation is %f\n",l);
}
I tried inserting print statements in the main function, and found that the value function is giving absurd results for simple polynomials, but the roots are correct for some polynomials but wrong for many. Why would the roots be correct for some if the algorithm was wrong?
There are so many problems in your code:
In main method,
printf("%d\n",value(p,-2,a));
Compiler should give you warning:
warning: format '%d' expects argument of type 'int', but argument 2 has type 'double'
Use %f instead of %d as value() returns float.
You are not allocating enough space and you are casting the return value of malloc. Casting the return value of malloc should be avoided since malloc returns a void * (which means that it needs no cast) and casting the return value can conceal errors. You can read more about this issue here.
p = (float *) malloc(a*sizeof(float));
to
p=malloc((a+1) * sizeof *p);
You are comparing floating ponit number here:
if(value(p,i,a)==0&&value(p,i+1,a)==0.00)
Don't do this, read What Every Computer Scientist Should Know About Floating-Point Arithmetic for the reason. You can use one of this (e.g nearlyEqual()) functions for your purpose.
In method bisect():
j=j;k=l;l=(j+k)/2; // j = j, kidding?
The biggest conceptual or mathematical error (apart from the programming errors explained in the other answer) is that you use integers for the arguments in the value function. It is rarely the case that random polynomials have integer roots. Rename n to x for intuitive readability and set the type of x to float.
Check again your assignment, if the prototype is really value(p,n,a), then maybe the intention is that n is the degree and a the evalution point, thus the signature should be (*float,int,float).
Using this signature, you should really use the Horner scheme to evaluate densely coded polynomials
float value(float *p, int deg, float a) {
int i;
float val = p[deg];
for(i=deg; i-- > 0; ) val = val*a+p[i];
return val;
}
and use descriptive names for variables in the bisection method (instead of j,k,l usually associated to integers) to avoid mixing them up
float left=a, right = a+1, mid =(left+right)/2;
etc.

-1.#IND00 output for certain input values

I'm trying to write a code that will take x as input and give cos(x) as output, using maclaurin's series.I'm using a while loop until the difference of two consecutive results is less then 0.001. I'm using double type to accomodate larger values.
the code works when x is in range [-2,2], but if x is greater or less than this range the ouput is -1.#IND00. Why is it happening? is the output value out of range ? how can i fix this ??
my code is :
#include <stdio.h>
double abs(double a);
double power(double p, int q);
int fact(int a);
int main()
{
int i=1,j=2*i;
double x,s=1.0,p,l=0.001;
printf("Enter x: ");
scanf("%lf", &x);
p = s+ power(-1,i) * power(x,j) / fact(j);
while (abs(p-s)>l){
i++; j=2*i;
s=p;
p = s+ power(-1,i) * power(x,j) / fact(j);
}
printf("cos(%f) = %f", x,p);
return 0;
}
double abs(double a)
{
if (a>=0) return a;
else return (-a);
}
double power(double p, int q)
{
int i;
double a=1.0;
for (i=0; i<q; i++){
a=a*p;
}
return a;
}
int fact(int a)
{
int i,p=1;
if (a==0 || a==1) return 1;
else
while (a!=1){
p=p*a;
a--;
}
return p;
}
update your scanf function to
scanf("%lf", &x);
Also you need to check pow and fact, these functions could overflow. Especially, fact which only use int.
As a larger |x| is use, more terms are needed and fact() overflows and strange results follow. Use double.
// int fact(int a)
double myfact(double p, int q) {
int i;
double a = 1.0;
for (i=0; i<q; i++){
a=a*p;
}
return a;
}
Eventually with values somewhere larger |x| > 30, other limitations kick in using this method. The limitation is due to precision and not range. For large values a significantly different algorithm should be used.
Potential conflict between int abs(int j) in <stdlib.h>. The prototyped may be found via stdio.h and conflicts with OP double abs(double a). In any case, abs() is a standard library function and OP should avoid that function name. Also recommend renaming power().
// double abs(double a)
double myabs(double a)

Resources