将浮点数 1864.78 转换为二进制和 IEEE 格式
Convert floating point number 1864.78 to binary and IEEE format
我一直在尝试将今天为 1864.78 的标准普尔 500 指数的值转换为它在内存中以 IEEE 单精度格式表示的方式。
转换小数的左边 (1864) 很容易。
11101001000.
但是如何获得小数 (.78) 的二进制表示?我尝试使用该技术,但它在 8 位指数 IEEE 格式上产生了许多数字:
.78*2=1.56 1
.56*2=1.12 1
.12*2=.24 0
.24*2=.48 0
.48*2=.96 0
.96*2=1.92 1
.92*2=1.84 1
.84*2=1.68 1
.68*2=1.36 1
.36*2=.72 0
.72*2=1.44 1
.44*2=.88 1(四舍五入因为现在我们总共有 23 位)
11101001000.110001111011 = 23 位尾数
符号加0
0 11101001000.110001111011
现在我需要将小数点移动 10 位
1.1101001000110001111011 x 2^10 指数现在是 10
加一个0位使全尾数为23位
1.11010010001100011110110
指数是 10 所以 10 + 127 = 137
等于 10001001
所以 0 10001001 11010010001100011110110 这是一个 32 位数。
这看起来是个不错的方法吗?我测试了这个值并写了这个问题我实际上能够自己解决它。
用这个测试十进制 FP。
http://www.h-schmidt.net/FloatConverter/IEEE754.html
您有两个不同的转换例程来将整数和小数部分转换为二进制。您了解如何将 1864
转换为二进制,但在将 .78
转换为二进制时遇到问题。 注意:您必须将内存中保存的实际分数转换为浮点数1864.78
,即1864.780029
或分数0.780029
不是 0.78
。这似乎是您 "rounding" 困惑的来源。
要将分数转换为其二进制表示形式,您需要将分数乘以 2
,如果所得数字的整数部分大于 1
,则该位的二进制表示形式为 1
,如果不是你的代表就是0
。如果大于一,则从数字中减去 1
并重复,直到用完数字或达到相关精度限制。例如:
number : 1864.78
float : 1864.780029 (actual nearest representation in memory)
integer : 1864
fraction : 0.780029
2 * 0.780029 = 1.560059 => integer part (1) fraction (0.560059) => '1'
2 * 0.560059 = 1.120117 => integer part (1) fraction (0.120117) => '1'
2 * 0.120117 = 0.240234 => integer part (0) fraction (0.240234) => '0'
2 * 0.240234 = 0.480469 => integer part (0) fraction (0.480469) => '0'
2 * 0.480469 = 0.960938 => integer part (0) fraction (0.960938) => '0'
2 * 0.960938 = 1.921875 => integer part (1) fraction (0.921875) => '1'
2 * 0.921875 = 1.843750 => integer part (1) fraction (0.843750) => '1'
2 * 0.843750 = 1.687500 => integer part (1) fraction (0.687500) => '1'
2 * 0.687500 = 1.375000 => integer part (1) fraction (0.375000) => '1'
2 * 0.375000 = 0.750000 => integer part (0) fraction (0.750000) => '0'
2 * 0.750000 = 1.500000 => integer part (1) fraction (0.500000) => '1'
2 * 0.500000 = 1.000000 => integer part (1) fraction (0.000000) => '1'
注意:浮点数小数值如何趋于零而不是达到您的位数限制。如果您尝试将 0.78
(无法精确表示为 32 位浮点值中的 1864.78
的分数),您将在第 12 位达到不同的转换。
将小数部分转换为二进制后,您可以继续转换为 IEEE-754 单精度格式。例如:
decimal : 11101001000
fraction : 110001111011
sign bit : 0
有偏指数的归一化为:
11101001000.110001111011 => 1.1101001000110001111011
exponent bias: 10
unbiased exponent: 127
__________________+____
biased exponent: 137
binary exponent: 10001001
转换为'hidden bit'格式形成尾数:
1.1101001000110001111011 => 1101001000110001111011
然后用符号位+余127指数+尾数组成IEEE -754 单精度表示:
IEEE-754 Single Precision Floating Point Representation
0 1 0 0 0 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 1 0 0 0 1 1 1 1 0 1 1 0
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|s| exp | mantissa |
仔细阅读,如果您还有其他问题,请告诉我。如果您想要一个简单的例程来使用转换结果填充字符数组,您可以执行类似于以下的操作以将浮点小数部分转换为二进制:
#define MANTISSA 23
...
/** return string containing binary representation of fraction
* The function takes a float as an argument and computes the
* binary representation of the fractional part of the float,
* On success, the function returns a null-terminated string
* containing the binary value, or NULL otherwise. The conversion
* is limited to the length of your MANTISSA (23-bits for single
* precission, 52-bits for double precision). You must insure
* you provide a buffer for 's' of at least MANTISSA + 1 bytes.
*/
char *fpfrc2bin (char *s, float fvalue)
{
/* obtain fractional value from fvalue */
float fv = fvalue > 1.0 ? fvalue - (int)fvalue : fvalue;
char *p = s;
unsigned char it = 0;
while (fv > 0 && it < MANTISSA + 1)
{ /* convert fraction */
fv = fv * 2.0;
*p++ = ((int)fv) ? '1' : '0';
*p = 0; /* nul-terminate */
fv = ((int)fv >= 1) ? fv - 1.0 : fv;
it++;
}
return s;
}
你太短了 1 位:IEEE754 binary32 格式使用 24 位有效数,但使用 23 位和隐式前导 1 存储。
所以最后2位是:
0.44*2=0.88 0 => 1
0.88*2=1.76 2 (rounded) => 0 (carry the extra bit)
给出了数字
1.110100100011000111101102×210
你已经计算出偏置指数(137 = 100010012),所以可以直接构造结果位模式:
0 10001001 11010010001100011110110
我一直在尝试将今天为 1864.78 的标准普尔 500 指数的值转换为它在内存中以 IEEE 单精度格式表示的方式。
转换小数的左边 (1864) 很容易。
11101001000.
但是如何获得小数 (.78) 的二进制表示?我尝试使用该技术,但它在 8 位指数 IEEE 格式上产生了许多数字:
.78*2=1.56 1
.56*2=1.12 1
.12*2=.24 0
.24*2=.48 0
.48*2=.96 0
.96*2=1.92 1
.92*2=1.84 1
.84*2=1.68 1
.68*2=1.36 1
.36*2=.72 0
.72*2=1.44 1
.44*2=.88 1(四舍五入因为现在我们总共有 23 位)
11101001000.110001111011 = 23 位尾数
符号加0
0 11101001000.110001111011
现在我需要将小数点移动 10 位
1.1101001000110001111011 x 2^10 指数现在是 10
加一个0位使全尾数为23位
1.11010010001100011110110
指数是 10 所以 10 + 127 = 137
等于 10001001
所以 0 10001001 11010010001100011110110 这是一个 32 位数。
这看起来是个不错的方法吗?我测试了这个值并写了这个问题我实际上能够自己解决它。
用这个测试十进制 FP。 http://www.h-schmidt.net/FloatConverter/IEEE754.html
您有两个不同的转换例程来将整数和小数部分转换为二进制。您了解如何将 1864
转换为二进制,但在将 .78
转换为二进制时遇到问题。 注意:您必须将内存中保存的实际分数转换为浮点数1864.78
,即1864.780029
或分数0.780029
不是 0.78
。这似乎是您 "rounding" 困惑的来源。
要将分数转换为其二进制表示形式,您需要将分数乘以 2
,如果所得数字的整数部分大于 1
,则该位的二进制表示形式为 1
,如果不是你的代表就是0
。如果大于一,则从数字中减去 1
并重复,直到用完数字或达到相关精度限制。例如:
number : 1864.78
float : 1864.780029 (actual nearest representation in memory)
integer : 1864
fraction : 0.780029
2 * 0.780029 = 1.560059 => integer part (1) fraction (0.560059) => '1'
2 * 0.560059 = 1.120117 => integer part (1) fraction (0.120117) => '1'
2 * 0.120117 = 0.240234 => integer part (0) fraction (0.240234) => '0'
2 * 0.240234 = 0.480469 => integer part (0) fraction (0.480469) => '0'
2 * 0.480469 = 0.960938 => integer part (0) fraction (0.960938) => '0'
2 * 0.960938 = 1.921875 => integer part (1) fraction (0.921875) => '1'
2 * 0.921875 = 1.843750 => integer part (1) fraction (0.843750) => '1'
2 * 0.843750 = 1.687500 => integer part (1) fraction (0.687500) => '1'
2 * 0.687500 = 1.375000 => integer part (1) fraction (0.375000) => '1'
2 * 0.375000 = 0.750000 => integer part (0) fraction (0.750000) => '0'
2 * 0.750000 = 1.500000 => integer part (1) fraction (0.500000) => '1'
2 * 0.500000 = 1.000000 => integer part (1) fraction (0.000000) => '1'
注意:浮点数小数值如何趋于零而不是达到您的位数限制。如果您尝试将 0.78
(无法精确表示为 32 位浮点值中的 1864.78
的分数),您将在第 12 位达到不同的转换。
将小数部分转换为二进制后,您可以继续转换为 IEEE-754 单精度格式。例如:
decimal : 11101001000
fraction : 110001111011
sign bit : 0
有偏指数的归一化为:
11101001000.110001111011 => 1.1101001000110001111011
exponent bias: 10
unbiased exponent: 127
__________________+____
biased exponent: 137
binary exponent: 10001001
转换为'hidden bit'格式形成尾数:
1.1101001000110001111011 => 1101001000110001111011
然后用符号位+余127指数+尾数组成IEEE -754 单精度表示:
IEEE-754 Single Precision Floating Point Representation
0 1 0 0 0 1 0 0 1 1 1 0 1 0 0 1 0 0 0 1 1 0 0 0 1 1 1 1 0 1 1 0
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|s| exp | mantissa |
仔细阅读,如果您还有其他问题,请告诉我。如果您想要一个简单的例程来使用转换结果填充字符数组,您可以执行类似于以下的操作以将浮点小数部分转换为二进制:
#define MANTISSA 23
...
/** return string containing binary representation of fraction
* The function takes a float as an argument and computes the
* binary representation of the fractional part of the float,
* On success, the function returns a null-terminated string
* containing the binary value, or NULL otherwise. The conversion
* is limited to the length of your MANTISSA (23-bits for single
* precission, 52-bits for double precision). You must insure
* you provide a buffer for 's' of at least MANTISSA + 1 bytes.
*/
char *fpfrc2bin (char *s, float fvalue)
{
/* obtain fractional value from fvalue */
float fv = fvalue > 1.0 ? fvalue - (int)fvalue : fvalue;
char *p = s;
unsigned char it = 0;
while (fv > 0 && it < MANTISSA + 1)
{ /* convert fraction */
fv = fv * 2.0;
*p++ = ((int)fv) ? '1' : '0';
*p = 0; /* nul-terminate */
fv = ((int)fv >= 1) ? fv - 1.0 : fv;
it++;
}
return s;
}
你太短了 1 位:IEEE754 binary32 格式使用 24 位有效数,但使用 23 位和隐式前导 1 存储。
所以最后2位是:
0.44*2=0.88 0 => 1
0.88*2=1.76 2 (rounded) => 0 (carry the extra bit)
给出了数字
1.110100100011000111101102×210
你已经计算出偏置指数(137 = 100010012),所以可以直接构造结果位模式:
0 10001001 11010010001100011110110