How does the below C macro example compile? - c

The code below does not give the correct output.
#include <stdio.h>
#define PI 22/7
#define AREA(r) PI * r * r
int main() {
printf("Pi: %d\n", PI);
printf("Area: %d\n", AREA(8));
return 0;
}
Whereas the code below gives the correct (nearest) output.
#include <stdio.h>
#define PI 22/7
#define AREA(r) r * r * PI
int main() {
printf("Pi: %d\n", PI);
printf("Area: %d\n", AREA(8));
return 0;
}
How exactly do these code differ?
Why is it so? I am not able to understand the difference between how both the above codes would give different answers.

The problem is your PI macro:
#define PI 22/7
There are two problems with this: (1) It's not wrapped in parentheses, to guard it against parts of it binding more tightly to other parts of the expression in which it's expanded, and (2) It's doing integer division.
If you have 22/7 by itself, it's just 3. Presumably that's not what you want. But the AREA macro, which also has problems, looks like this:
#define AREA(r) r * r * PI
With PI expanded, this is equivalent to:
#define AREA(r) r * r * 22/7
Assuming r is a simple variable or constant, this is equivalent to:
#define AREA(r) (r * r * 22) / 7
If r is an integer, it's still doing integer division, but it's only truncating at the end, so the result will be more accurate.
Note that AREA has two problems of its own: (1) It's not wrapping its argument, r, in parentheses, and (2) It's not wrapping the expression as a whole in parentheses.
For problem (1), imagine passing something like 2+3 as r. Since multiplication associates more tightly than addition, this clearly won't do what you want.
If you want an accurate result, you would normally use an accurate floating-point value for pi, rather than the extremely inaccurate approximation 22/7. But if you do want to use 22/7, you should still use a floating point value for it:
#define PI (22.0/7.0)
Then you can fix AREA:
#define AREA(r) (PI * (r) * (r))
This will properly protect the arguments and final results from reassociating after expansion, but note that the result will have type double. Also note that its argument, r, is evaluated twice.
But a better approximation to pi is preferable. On Linux, math.h exports M_PI, which is far more accurate.

Try expanding the macro. The first one is 22 / 7 * 8 * 8. All values are integers, so you get rounding errors and the calculation is basically 3 * 8 * 8 = 192.
The second expression is 8 * 8 * 22 / 7. So the calculation is 1408 / 7 = 201.

Multiplication and division is done from left to right.
So, AREA(8) in the first example expands to
22/7 * 8 * 8 which is evaluated like so:
(((22/7) * 8) * 8), i.e 3 * 8 * 8 = 192.
The other variant gives:
(((8*8)*22)/7) = (64 * 22)/7 = 1408/7 = 201.
If you want better precision, use floating point, i.e.
#define PI (22.0/7.0)
or, why not use a better approximation of pi:
#define PI (3.141593)
But then you should use %f in printf. (as commented by Jabberwocky)

Related

Output of this program is 64. Can someone explain how?

#define sqr(a) a*a
int main()
{
int i;
i = 64 / sqr(4); //answer of this expression is 64.
printf("%d", i);
return 0;
}
In this code the output is 64, and according to the rules, the expression i = 64 / sqr(4) should be solved as i = 64 / 4*4, which gives a result of 4, but the output of the program is 64. Why?
Macros are not evaluated like functions, they are expanded in place. The statement
i = 64 / sqr(4);
expands to
i = 64 / 4*4;
Both of the multiplication and division operators have the same precedence and are left-associative, so the above statement is parsed as
i = (64 / 4) * 4;
Thus, you are multiplying the result of 64 / 4 by 4, rather than dividing 64 by the result of 4 * 4.
They way to avoid precedence and associativity issues with macros like this is to enclose the expansion in parentheses:
#define sqr(a) (a * a)
By itself, though, that’s not sufficient - if you do something like sqr(1+2), that will expand to (1+2*1+2), which evaluates to 5 instead of the expected 9. You also need to parenthesize the argument(s) as well as the overall expression:
#define sqr(a) ((a) * (a))
Now your statement expands to
i = 64 / ((4) * (4));
and will evaluate to what you expect.
I'll try to keep this answer simple:
Macros is a set of code that just get replaced at the time of compilation.
Now, if you replace sqr(4) with 4*4
It becomes something like: 64/4*4.
Now, if you apply basic rule of BODMAS. It gets executed as follows:
64/4= 1616*4= 64 i.e first division with 4 then multiplication with 4 that gives 64
You need to look at the order of operations. Multiplication is done first, so it meant (64 * 4) / 4. Here's an updated version with parenshases around your macro:
#define sqr(a) ((a)*(a))
int main()
{
int i;
i = 64 / sqr(4); //answer of this expression is 4.
printf("%d", i);
return 0;
}

Program always outputs 0 value

#include <stdio.h>
void volume()
{
float pi=3.14,r,v;
printf("\nEnter the radius: ");
scanf("%f",&r);
v=(1/3)*pi*r*r*r;
printf("%f",v);
}
int main()
{
volume();
}
This is C program to find volume using functions.
Compiler shows no error or warnings but the output is always zero.
you have zero here due to 1/3 is integer division = 0
replace v=(1/3)*pi*r*r*r; with v=(1.f/3.f)*pi*r*r*r;
That's because anything multiplied by 0 is 0, and 1/3 is 0.
1/3 is 0 because both 1 and 3 are literals of type int, and dividing two integers results in an integer again.
Fix: 1.0/3.0 because 1.0 and 3.0 are floating point literals, so you get floating-point division.
It's due to the fact that 1 / 3 is done as integer division because both operands are type int(a). So the final result is zero.
You can get the intended effect simply by ensuring one of the operands is non-integer, such as with:
v = (1.0f / 3) * pi * r * r * r;
That will work, because it results in a float (inside the parentheses) of 0.333.... However, there's absolutely no real reason why you need to parrot the equation shown in text books, you can achieve the same result with the simpler:
v = pi * r * r * r / 3;
Because all those variable are floating point, the result of the final something / 3 is also done as floating point.
And, just some quick advice, you may want to consider using double types rather than float. The float type generally uses less space but, unless you have large arrays of them, it's not usually a problem. The double type gives a much greater range and precision.
In addition, 3.14 is not really that precise a value for pi. Most implementations will define an M_PI constant in math.h for you to use but it's not mandated by the standard. So, you can use something like this to get a more accurate value:
#include <stdio.h>
#include <math.h>
// Define if implementation doesn't provide.
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static void GetRadiusAndPrintVolume(void) {
printf("\nEnter the radius: ");
double radius;
scanf("%lf", &radius);
double volume = M_PI * radius * radius * radius / 3;
printf("Volume for radius %f is %f\n", radius, volume);
}
int main() {
GetRadiusAndPrintVolume();
}
And, finally, you may want to check that equation of yours. Though you don't say explicitly, it very much looks like it's supposed to be the volume of a sphere.
If that is the case, the formula should be 4/3 π r3 rather than 1/3. Hence the statement would be:
double volume = M_PI * radius * radius * radius * 4 / 3;
(a) If you're interested, this is all covered by the "Usual arithmetic conversions" section of the C standard (section 6.3.1.8 in C11):
Many operators that expect operands of arithmetic type cause conversions and yield result types in a similar way. The purpose is to determine a common real type for the operands and result.
It then goes on to list what happens for specific cases, which is generally that the "lesser" (in terms of its range and/or precision) operand is upgraded to the same type as the "greater" operand. That's the basic idea though, if you want the full picture, you should refer to the previously mentioned section.
In your specific case, since both operands of 1 / 3 are of type int, the calculation and the result is done as an int, meaning it truncates the fractional part (giving zero).
Because 1/3 is not 0.3333 in C, it is 0.
Solution:
#include <stdio.h>
void volume()
{
float pi=3.14,r,v;
printf("\nEnter the radius: ");
scanf("%f",&r);
v=(((float)1)/3)*pi*r*r*r;
printf("%f",v);
}
int main()
{
volume();
}

Mathematical task with point numbers

I just started to study about C Programing.
I want to write a program to solve this mathematical task (1/2*r2*3.14)
This is the code that I wrote:
#include <stdio.h>
#include <conio.h>
main()
{
int r=5;
float sum;
sum = 1/2*r^2*3.14;
printf("%f", sum);
getch();
}
but there is an error and I don`t know what the mistake is.
First I thought that there is something wrong about the number 3.14, but when I changed it to 3 the program ran but the answer was 6.0000 but it should be 37.5
In C there is no operator for power calculation. ^ is used as XOR operator. You need to use library function pow for power calculations.
sum = 1.0 / 2 * pow(r,2) * 3.14;
Note that I changed 1/2 to 1.0/2 because 1/2 will always give 0 and the result you will get is 0.
^ is bitwise XOR operator. You have to use pow() for your purpose
sum = 1.0/2.0*pow(r,2)*3.14;
Your code will give you 6.000. Because ^ is using as xor operator
1/2*r^2*3 = (0)d ^ (6)d = (000)b ^ (110)b = (110)b = (6)d
But, 3.14 instead of 3 will give you error
1/2*r^2*3.14
Because, Xor operator don't take double as operand
The ^ operator is not for power raising you can write it explicitly
#include <stdio.h>
#include <conio.h>
main()
{
int r=5;
float sum;
/* 1/2 * r^2 * pi <- this is the expression */
sum = 1.57 * r * r;
printf("%f", sum);
getch();
}
the expression has no meaning in the program except for someone reading it, so you can add a comment and write the values directly.
And in case you are going to raise to a higher power just use the pow() function.
Also, if you skip the .0 the compiler assumes the values as integers, and 1/2 is 0.5 truncated it yeilds 0, 1./2 would also work, but not 1/2.

Casting int as a double is returning #INF00

So I am trying to cast (3/17) as double. This is for an assignment so the professor wants it to be this way for some reason.
I am trying to cast it by doing the following:
(double)(3/17)
Actual code:
int assignment7()
{
#include <stdio.h>
#define PI 3.14
int a=0;
double Ny=0,y=0,z=0,x=0,amod2=0;
printf("Enter values for x,y,z and a(must be an odd number): ");
scanf("%lf%lf%lf%d",&x,&y,&z,&a);
amod2=a%2;
printf("%.2lf\n",test);
Ny=y / (double)(3/17) - z + x / amod2 + PI;
printf("%lf\n",Ny);
}
The problem is occurring on the second to last line where it is interpreting 3/17 as an int thus it would equal 0. y / 0
Professors exact instructions:
"General equation: y = y / (3/17) - z + x / (a % 2) + PI (recall: a is an integer; the 3 and 17 constants in the equation should be left as integers initially, but explicitly type-casted as floating-point values)"
(3/17) is equal to 0 because it is evaluated using integer arithmetic, and so you get a divide by zero, which is of course a run-time error. Change:
(double)(3/17)
to:
(3.0 / 17.0)
Note that the cast is redundant.
You have a division by zero as 3/17 is zero.
Instead use doubles to begin with: 3.0 / 17.0, then you don't even need the cast.

Why doesn't this math work with macros? [duplicate]

This question already has answers here:
some error in output in using macro in C
(3 answers)
Closed 9 years ago.
Why doesn't this math work with macros in C?
#include <stdio.h>
#define FOO 6
#define BAR 32
#define MULT FOO * BAR
main() {
int x = 28296;
int y = x / MULT;
printf("%d / %d = %d\n", x, MULT, y);
return 0;
}
The result of this is:
28296 / 192 = 150912
Why isn't it 147? If I set a variable " int mult" equal to MULT, and use the variable in the expression (int y = x / mult) it works as expected.
#define tells the preprocessor to replace the code before compilation, so your line actually says:
int y = x / 6 * 32;
since * and / operators have the same precedence, and are evaluated from left to right, you get (x/6) * 32. The compiler would probably do this calculation for you since x is known to it.
Instead, use parenthesis when defining macros like this
Put a bracket around the macro:
#define MULT (FOO * BAR)
Now, you'll get 147.
The reason getting 150912 is that after macro expansion the expression is equivalent to:
y = 28296 / 6 * 32;
and hence it's evaluated as 28296/6 and then multiplied by32.
As #kevin points out, it's better to put brackets around FOO and BAR as well in general case to avoid surprises like this.

Resources