// IEEE float format:
// sign exponent fraction bias
// single precision 1[31] 8[30-23] 23[22-00] 127
// double precision 1[63] 11[62-52] 52[51-00] 1023
//
// Convert the following single-precision IEEE 754 number into
// a floating-point decimal value.
//
// 1 10000001 10110011001100110011010
//
// first, put the bits in three groups.
// Bit 31(the leftmost bit) show the sing of the number.
// Bits 23-30(the next 8 bits) are the exponent.(指数).
// Bits 0-22(on the right) give the fraction.(分数).
// single-precision bias is 127.
// second, look at the sign bit.
// If this bit is a 1, the number is negative.
// If it is 0, the number is positive.
// This bit is 1, so the number is negative.
// Get the exponent and the correct bias.
// The exponent is simply a positive binary number.
// 10000001bin = 129ten
// Remember that we will have to subtract a bias from this exponent
// to find the power of 2. Since this is a single-precision number,
// the bias (偏差) is 127.
// Convert the fraction string into base ten.
// This is the trickiest step. The binary string represents a fraction,
// so conversion is a little different.
// Binary fractions look like this:
// 0.1 = (1/2) = 2^-1
// 0.01 = (1/4) = 2^-2
// 0.001 = (1/8) = 2^-3
// So, for this example, we multiply each digit by the corresponding
// power of 2:
// 0.10110011001100110011010bin=1*2^-1 + 0*2^-2 + 1*2^-3 + ...
// = 1/2+1/8+1/16+...
// Note that this number is just an approximation on some decimal
// number. There will most likely be some error. In this case, the
// fraction is about 0.7000000476837158.
// This is all the information we need. We can put these numbers in
// the expression:
// (-1)^sign bit * (1+fraction) * 2^(exponent-bias)
// = (-1)^1 * (1.7000000476837158) * 2^(129-127)
// = -6.8
// The answer is approximately -6.8.
//
// over.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
// v - value that will be packed.
// size - width
// fsize - precision width
int f2i(float v, int size, int fsize)
{
char* buf, *p;
int ret;
buf = (char*)malloc(sizeof(char)*(size+2));
/*
* 动态设置宽度/精度
*
* 在许多时候,我们或许还希望这些格式控制符中用以指定长度信
* 息的数字是动态的,而不是静态指定的,因为许多时候,程序要
* 到运行时才会清楚到底需要取字符数组中的几个字符,这种动态
* 的宽度/精度设置功能在sprintf 的实现中也被考虑到了,
* sprintf 采用”*”来占用一个本来需要一个指定宽度或精度的常数
* 数字的位置,同样,而实际的宽度或精度就可以和其它被打印的
* 变量一样被提供出来,于是,可以变成:
* sprintf(s, "%.*s%.*s", 7, a1, 7, a2);
* 或者:
* sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2);
*/
// 利用IEEE float的内部实现来pack 浮点数
sprintf(buf, "%*.*f", size, fsize, v);
printf("%s\n", buf);
p = strchr(buf, '.');
while(*p = *(p+1))
p++;
ret = atoi(buf);
free(buf);
return ret;
}
int main(int argc, char* argv[])
{
float val = 1234.4567;
int i = f2i(val, 8, 8);
cout << "f2i: " << i << endl;
return 0;
}