floating point exception(core dumped) - c

I tried with putting puts("..") to find where the mistake is, but it didn't help.
this is my third function, first and second are working.
i translated in englih, i hope it's understandably.
void write3(sth_st*E, int n, char* Typ){
int i;
int sum=0;
int count=0;
float result;
for(i=0; i<n; i++){
if(strcmp(Typ, E[i].typ)==0){
sum=sum+E[i].time;
count++;
}
}
FILE*write3;
write3=open("xD", "w");
puts("rand");
result=sum/count;
fprintf(write3, "%f", result);
return;
}

count is most likely integer and 0. The system error message is misleading, especially since dividing by 0 is perfectly valid for floating point values.
With the extra context, we can infer that Typ was not found in the E array or maybe n is too small, so count and sum both stay at 0 and the division sum/count invokes undefined behavior because it is an integer division.
If you convert one or the other to double, you will get a floating point division, which is undoubtedly what you expect and printf will print nan for this case.
result = (double)sum / count;
There is also a possiblity that the sum of all times may overflow the int type. You should make sum a double to avoid that.
Note that %f is the printf format for double. result is a float, but luckily floats are silently converted to double when passed to printf. There is no benefit at using float types, use double instead.

Related

The problem about printf function to "output float with %d" in C

I am a newbie to the C language. When I was learning floating point numbers today, I found the following problems.
float TEST= 3.0f;
printf("%x\n",TEST);
printf("%d\n",TEST);
first output:
9c9e82a0
-1667333472
second output:
61ea32a0
1642738336
As shown above, each execution will output different results. I have checked a lot of IEEE 754 format and still don't understand the reasons. I would like to ask if anyone can explain or provide keywords for me to study, thank you.
-----------------------------------Edit-----------------------------------
Thank you for your replies. I know how to print IEEE 754 bit pattern. However, as Nate Eldredge, chux-Reinstate Monica said, using %x and %d in printf is undefined behavior. If there is no floating point register in our device, how does it work ? Is this described in the C99 specification?
Most of the time, when you call a function with the "wrong kind" (wrong type) of argument, an automatic conversion happens. For example, if you write
#include <stdio.h>
#include <math.h>
printf("%f\n", sqrt(144));
this works just fine. The compiler knows (from the function prototype in <math.h>) that the sqrt function expects an argument of type double. You passed it the int value 144, so the compiler automatically converted that int to double before passing it to sqrt.
But this is not true for the printf function. printf accepts arguments of many different types, and as long as each argument is right for the particular % format specifier it goes with in the format string, it's fine. So if you write
double f = 3.14;
printf("%f\n", f);
it works. But if you write
printf("%d\n", f); /* WRONG */
it doesn't work. %d expects an int, but you passed a double. In this case (because printf is special), there's no good way for the compiler to insert an automatic conversion. So, instead, it just fails to work.
And when it "fails", it really fails. You don't even necessarily get anything "reasonable", like an integer representing the bit pattern of the IEEE-754 floating-point number you thought you passed. If you want to inspect the bit pattern of a float or double, you'll have to do that another way.
If what you really wanted to do was to see the bits and bytes making up a float, here's a completely different way:
float test = 3.14;
unsigned char *p = (unsigned char *)&test;
int i;
printf("bytes in %f:", test);
for(i = 0; i < sizeof(test); i++) printf(" %02x", p[i]);
printf("\n");
There are some issues here with byte ordering ("endianness"), but this should get you started.
To print hex (ie how it is represented in the memory) representation of the float:
float TEST= 3.0f;
int y=0;
memcpy(&y, &TEST, sizeof(y));
printf("%x\n",y);
printf("%d\n",y);
or
union
{
float TEST;
int y;
}uf = {.y = 0};
uf.TEST = 3.0f;
printf("\n%x\n",(unsigned)uf.y);
printf("%d\n",uf.y);
Both examples assuming sizeof(float) <= sizeof(int) (if they are not equal I need to zero the integer)
And the result (same for both):
40400000
1077936128
As you can see it is completely different from your one.
https://godbolt.org/z/Kr61x6Kv3

Assigning a value to a float variable changes the value in C

I am trying to calculate an average of integer numbers and assign it to a float variable. When I debug it with cgdb and print the right side of the average calculation, it gives me the right number. However, when I assign it to the (float*)payload the value changes from 401850471 to 401850464.00.
float sum= 0.0;
for (int i = 0;
i<avg_operator->data_source->column_pointer.result->num_tuples;
i++) {
sum+= ((int*)avg_operator->data_source->column_pointer.result->payload)[i];
}
((float*)avg_operator->result->payload)[0]=
sum/(float)avg_operator->data_source->column_pointer.result->num_tuples;
You cannot convert an int to a float by casting their pointers, that gives a random / undefined value. You need to dereference the float pointer, and assign the value.
that:
((float*)avg_operator->result->payload)[0]= sum/(float)avg_operator->data_source->column_pointer.result->num_tuples;
isn't casting, it's lying to the compiler. You should dereference, and no need to cast to float, as the conversion to integer is done automatically:
avg_operator->result->payload[0]= sum/(float)avg_operator->data_source->column_pointer.result->num_tuples;
(well, maybe you need to round the value instead of truncating, though)
also, since payload is an integer, no need to cast to integer pointer as well, just do:
sum+= avg_operator->data_source->column_pointer.result->payload[i];
and define sum as a float, one never knows with floating point accumulation error (if the sum isn't too big for an integer, that is)
When I debug it with cgdb and print the right side of the average calculation, it gives me the right number.
The debugger is showing the quotient using double math. C allows float division to use wider types. But once the quotient is assigned to a float, precision narrowing may occur.
401850471 is a 29 bit value. A float typically has 24 bits of precision. Something must give.
401850464.0 is the closest representable float to 401850471, so that speaks well to that at least there is a reasonable result.
OP is also doing other strange code manipulations. A recommend solution begins with a wider sum type and more precise division and storage.
long long sum = 0.0;
int n = avg_operator->data_source->column_pointer.result->num_tuples
int *data = (int*)avg_operator->data_source->column_pointer.result->payload;
for (int i = 0; i < n; i++) {
sum += data[i];
}
double average = 1.0 * sum / n;
printf("Average %f\n", average);
If the answer must be a float, code must live with a rounded (in a binary sense) average.

Wrong answer of average function?

I'm practically new to C programming and I've been trying to get a simple average function right, but the fractional part of the answer keeps messing up...??
#include <stdio.h>
#include <float.h>
float cal(int num1,int num2,int num3);
int main(){
int a,b,c;
float avg;
a=10;
b=5;
c=11;
avg=cal(a,b,c);
printf("Average is : %E\n", avg);
return 0;
}
float cal(int num1,int num2,int num3){
float avg1;
avg1=(num1+num2+num3)/3;
return avg1;
}
The answer (avg) should be 8.66666666667, but instead I get 8.00000000...
You're doing integer division here. Cast it to float (at least one of them) or use float literals before division to force it to use float division.
For example, change
avg1=(num1+num2+num3)/3;
to
avg1=(num1+num2+num3)/(float)3; // 1. cast one to float
avg1=(num1+num2+num3)/3.0f; // 2. use float literals
Change this
avg1=(num1+num2+num3)/3;
to this
avg1=(num1+num2+num3)/(float)3;
That way you force a division by a float.
With your code you actually perform integer division, which means that the decimal digits get discarded. Then the result of the division is assigned to a float number, but the decimal digits are already gone. That's why you need to cast at least one operand of the division to a float, in order to get what you want.
It is because all operands are integer in here (num1+num2+num3)/3. So you get an integer division, that is later cast to a float (i.e. upon the assignment, but after the evaluation).
You need to make one of the division operands a float, so the rest will be converted. And the division will be a float division.
E.g:
(num1+num2+num3)/(float)3
(num1+num2+num3)/3.0f
((float)(num1+num2+num3))/3
Note that the additions are still integer additions, because of parentheses.
A nice read on the conversion rules is here.
Force the division to be perfomed in floating point
avg1=(num1+num2+num3)/3.0f;
What happens in your case is, you perform the an integer division and then convert it to float:
Resulting type of (num1+num2+num3)/3 is an integer, while the type of (num1+num2+num3)/3.0f is a float.
Integer division will give the result without the decimal point.
Change
avg1=(num1+num2+num3)/3;
to
avg1=(float)(num1+num2+num3)/3;
If you perform integer division then result will also be integer.
As avg1 is already declared as float, you can cast the result of the operation to get float value.
You can simplify your code further
float cal(int num1,int num2,int num3){
return ((num1+num2+num3)/3.0);
}
Just change the value 3 to 3.0 that's enough. because the up-casting has to be made manually the compiler only perform the down-casting.
In addition to the well pointed out need to use floating point division rather than integer division, typical float will not provide a precise number like 8.66666666667 but only to 6 or so digits. Further, conversion of typical int (32-bit) may result in truncation when converting to float.
For a more precise answer with 11 digits to the rights of ., use double instead of float
double cal(int num1,int num2,int num3){
double avg1;
avg1=(num1+num2+num3)/3.0; // 3 --> 3.0
return avg1;
}
int main(void){ // added void
int a,b,c;
double avg;
a=10;
b=5;
c=11;
avg=cal(a,b,c);
// printf("Average is : %E\n", avg);
printf("Average is : %.11E\n", avg); // Print to 11 digits after the dp.
return 0;
}

Why does 1/2 in c = -2010232232?

I have a very simple C program.
int main(void){
double sum = 1/2;
printf("%d\n", sum);
return 0;
}
Why does it return a number like "-2030243223"?
And why does this number change every time I run the program?
I've tried using int's and float's but I can't seem to get the output to be 0.5!?
Use %f to print a double, not %d. The latter causes undefined behavior.
Also the expression 1/2 uses integer division which yields 0, so to get .5, use 1/2. (note trailing period).
Finally, to actually get .5 instead of something like 0.500000, specify the precision:
printf("%.1f\n", sum);
You're passing an IEEE floating-point number to printf, but telling it it's an integer.
Change
printf("%d\n", sum);
to
printf("%f\n", sum);
As noted in other comments, you probably also want to do floating-point division rather than integer division. 1/2 is zero; you're dividing two integers, so the result is an integer (yes, even though you're about to assign it into a floating-point variable -- each expression's type is determined in isolation) and it has to discard the remainder. You probably want 1.0/2 instead; if either term is a float, then the result is a float, so you'll get 0.5.
You're trying to print a double to an Integer. (%d).
Even though they both are numbers, internally there are huge differences, for example, memory ones.
You're trying to print a double as an int. Try using:
printf("%g\n");
Also, you will want to make you initial division 1.0/2.0 or else you will get 0.
Try this:
int main(void){
double sum = 1.0/2.0;
printf("%10.3f\n", sum);
return 0;
}
There is a couple of issues with your code
int main(void){
// you need to divide a double by a double, not two ints
double sum = 1.0/2.0;
// %d is for int, not doubles. You use %f in the case of printing a double
printf("%f\n", sum);
return 0;
}
Now if you really want to print the variable as an int, you can cast the variable sum as an int by doing printf("%d\n", (int)sum);, but you'll have a rounding issue.
Try the following:
printf("%f\n", sum);
%d is a placeholder for integer, maybe the address of sum has been printed out^^
The bad format can't be the whole answer, because:
With OP's code, the double should be zero, stored as 0x0000000000000000, which couldn't show as "-2030243223" (0x86FCF269).
OP says this value changes all the time.
So there must be something else, such as the fact that the header is missing: I guess the compiler doesn't know printf is a variadic function, and tries to pass the argument through floating-point registers.
printf, being a variadic function, probably attempts to read its input value from the stack, hence garbage.

Why we can't use operator % for float and double type operands?

I am new to C/C++, so I have a couple of questions about a basic type:
I have read somewhere that the operator % can't be applied to float or double type operands.
Then how can I check the divisibility of float or double type variables? I have shown my program with error below:
#include <stdio.h>
int main()
{
double n,k,t,i;
int j=0;
scanf("%f %f",&n,&k);
i=0;
while(i<n)
{
scanf("%f",&t);
if(t%k==0) /* error:invalid operands to binary % */
j++;
i++;
}
printf("%d",j);
return 0;
}
If a positive integer has a range up to 10^9, which qualifier should I use or how to achieve such a large range?
then how can i check the divisibility of float or double type variables. ??`
Use fmod. % only work with integer operands. % does not work with floating point values because C already provides the fmod library function.
Use the function fmod and its family.
a. if you want to keep it in floating point, use the fmod function from <math.h> (std::fmod from <cmath> in C++).
b. the int range is implementation-dependent (although the standard defines a minimum range that, IIRC, should be of +-32767, although on typical machines it will be -2147483648 - 2147483647). If an integer number is in the range of int you don't have to do anything particular - an integer literal without suffixes is automatically taken for an int if it fits in its range. On the other hand, bigger integer literals may need to be stored in a long or long long to avoid overflow.
Here is an alternative to the fmod answers - which answer the question you originally asked (since you were using double type. If, as is clear from your comments, you actually want to use integer types only, you can rewrite your code as follows (with the unsigned long long int type to give you plenty of headroom):
#include <stdio.h>
int main()
{
unsigned long long int n, k, t, i, j=0;
printf("enter the number of attempts: ");
scanf("%llu", &n);
printf("\nEnter the factor: ");
scanf("%llu", &k);
i=0;
while(i<n)
{
printf("\nEnter the number to test: ");
scanf("%llu",&t);
if(t%k==0)
j++;
i++;
}
printf("The number of multiples found was %llu\n", j);
return 0;
}
Note I have attempted to make the I/O a little more descriptive - it is a good idea to prompt the user, rather than just have a blinking cursor waiting for him. Obviously I am guessing at the prompts a bit (may not even be the language you want to use...)
% can't be used on floats because the standard says so. Use fmod. Okay okay okay, the actual reason is that the concept of a "remainder" only makes sense for integer division. What fmod does is produce an integer quotient for two floating-point arguments:
float my_fmod(float a, float b)
{
int quot = (int) a/b;
return a - (quot * b);
}
If you need a specific range for an integer, don't use int with qualifiers since they are implementation-specific. Use a fixed-width type like uint32_t.

Resources