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 |