移植性をあきらめ、IEEEfloat
と 32 ビットを想定しますint
。
// Doesn't check for NaN or denormalized.
// Left as an exercise for the reader.
void pbits(float x)
{
union {
float f;
unsigned i;
} u;
int sign, mantissa, exponent, i;
u.f = x;
sign = u.i >> 31;
exponent = ((u.i >> 23) & 255) - 127;
mantissa = (u.i & ((1 << 23) - 1)) | (1 << 23);
for (i = 0; i < 24; ++i) {
if (mantissa & (1 << (23 - i)))
printf("2^%d\n", exponent - i);
}
}
これにより、指定された浮動小数点数になる 2 のべき乗が出力されます。例えば、
$ ./a.out 156
2^7
2^4
2^3
2^2
$ ./a.out 0.333333333333333333333333
2^-2
2^-4
2^-6
2^-8
2^-10
2^-12
2^-14
2^-16
2^-18
2^-20
2^-22
2^-24
2^-25
1/3 がどのように切り上げられるかを確認できますが、小数点以下の桁数に関係なく常に小数点以下を切り捨てるため、直感的ではありません。
脚注:次のことは行わないでください。
float x = ...;
unsigned i = *(unsigned *) &x; // no
のトリックは、union
警告を生成したり、コンパイラを混乱させたりする可能性がはるかに低くなります。