1,576 views
8 votes
8 votes
int foo1(float a)
{
    int b = a;
    return b/2;
}
int foo2(double a)
{
    int b = a;
    return b/2;
}
int foo3(unsigned int a)
{
    int b = a;
    return b/2;
}

Consider the above three C functions and choose the best option given below. (Assume IEEE floating point representation and 4 bytes for int)

  1. All 3 functions return the same value for all input integer values
  2. foo1 and foo2 throw compile time error
  3. foo2 and foo3 return the same value for all input integer values but not foo1
  4. All 3 functions return different value for some input integer values

1 Answer

Best answer
5 votes
5 votes

Answer to this is C. The answer depends on IEEE floating point representation. Fortunately or not, that is also part of GATE syllabus. So lets see. IEEE 754 representation for float has

  • 1 sign bit
  • 8 exponent bits with a bias 127. i.e., actual exponent value needs to be subtracted by 127.
  • 23 mantissa bits

So, for say 0.25 we get

  • Sign bit 0
  • Exponent bits are 01111101
  • Mantissa bits are all 0s.

So, how we get 0.25 from these bits? Just apply the IEEE 754 formula

Signbit. (1.mantissa bits) 2^(EXponent bits - bias)

1 is added before "." because if exponent is nonzero, IEEE 754 uses normalized representation.

$= 1.0 \times 2^{125 -127} = 1.0 \times 2^{-2} = 0.25$.

Now, say for $2^{31} - 1$, we get a similar representation but the catch here is in Integer representation we have 31 bits for this, while in float representation, we have only 24 (23 + 1 implicit from normalized representation). i.e., we loose the information held by those 7 bits and when we convert that float value back to integer, we get a different one - approximated to the nearing integer which could be represented by float. For example, consider the following code

#include<stdio.h>


void printbits(char a)
{
        int i;int flag = 1<<7;
        for(i=0; i< 8; i++){
                printf("%hu",(a & flag) > 0 );
                flag>>=1;
        }
        printf(" | ");
}
void printbinary(int a)
{
        int i;char *p = ((char*)&a) + sizeof a - 1;
        for(i=sizeof(a); i >0; i--)
        {
                printbits(*p);
                p--;
        }
        printf("\n\n");
}
void printbinaryf(float a)
{
        int i;char *p = ((char*)&a) + sizeof a - 1;
        for(i=sizeof(a); i >0; i--)
        {
                printbits(*p);
                p--;
        }
        printf("\n\n");
}
void printbinaryd(double a)
{
        int i;char *p = ((char*)&a) + sizeof a - 1;
        for(i=sizeof(a); i >0; i--)
        {
                printbits(*p);
                p--;
        }
        printf("\n\n");
}



int foo1(float a)
{
        printf("\nFloat: %f\n", a);
	printbinaryf(a);
    int b = a;
    return b/2;
}
int foo2(double a)
{
        printf("\nDouble: %lf\n", a);
	printbinaryd(a);
    int b = a;
    return b/2;
}
int foo3(unsigned int a)
{
        printf("\nUnsigned Int:  %d\n", a);
	printbinary(a);
    int b = a;
    return b/2;
}
int main()
{
	int a = (1<< (8 * sizeof(int) - 2)) - 1;
	//printf("%d %d %d", foo1(a), foo2(a), foo3(a));
	
        printf("\nInt: %d\n", (int)a);
	printbinary(foo1(a));
	printbinary(foo2(a));
	printbinary(foo3(a));

}

Output is:

Int: 1073741823

Float: 1073741824.000000
01001110 | 10000000 | 00000000 | 00000000 | 

00100000 | 00000000 | 00000000 | 00000000 | 


Double: 1073741823.000000
01000001 | 11001111 | 11111111 | 11111111 | 11111111 | 10000000 | 00000000 | 00000000 | 

00011111 | 11111111 | 11111111 | 11111111 | 


Unsigned Int:  1073741823
00111111 | 11111111 | 11111111 | 11111111 | 

00011111 | 11111111 | 11111111 | 11111111 |
selected by
Answer:

Related questions

3 votes
3 votes
2 answers
2
8 votes
8 votes
2 answers
3
1 votes
1 votes
3 answers
4