如何将 IEEE 754 单精度二进制浮点数转换为十进制数? [英] How to convert an IEEE 754 single-precision binary floating-point to decimal?
问题描述
我正在开发一个需要将 32 位数字转换为十进制数的程序.
I am working on a program that needs to convert a 32-bit number into a decimal number.
我从输入中得到的数字是一个 32 位数字,表示为浮点数.第一位是符号,接下来的 8 位是指数,其他 23 位是尾数.我正在用 C 语言编写程序.在输入中,我将该数字作为 char[]
数组,然后我在其中创建一个新的 int[]
数组存储符号、指数和尾数.但是,当我尝试将尾数存储为某种数据类型时,我遇到了尾数问题,因为我需要将尾数用作数字,而不是数组: formula=sign*(1+0.mantissa)*2^(exponent-127)
.
The number that I get from input is a 32 bit number represented as floating point. The first bit is the sign, the next 8 bits are the exponent, and the other 23 bits are mantissa. I am working the program in C. In input, I get that number as a char[]
array, and after that I am making a new int[]
array where I store the sign , the exponent and the mantissa. But, I have problem with the mantissa when I am trying to store it in some datatype, because I need to use the mantissa as a number, not as an array: formula=sign*(1+0.mantissa)*2^(exponent-127)
.
这是我用来存储尾数的代码,但程序仍然给我错误的结果:
Here is the code I use to store the mantissa, but still the program gets me wrong results:
double oMantissa=0;
int counter=0;
for(counter=0;counter<23;counter++)
{
if(mantissa[counter]==1)
{
oMantissa+=mantissa[counter]*pow(10,-counter);
}
}
mantissa[]
是一个 int
数组,我已经从 char
数组转换了尾数.当我从 formula
得到值时,它必须是一个二进制数,我必须将它转换为十进制,所以我会得到这个数字的值.你能帮我存储尾数的 23 位吗?而且,我不能使用像 strtoul
这样将 32 位数字直接转换为二进制的函数.我必须使用公式
.
mantissa[]
is an int
array where I have already converted the mantissa from a char
array. When I get the value from formula
, it has to be a binary number, and I have to convert it to decimal, so I will get the value of the number. Can you help me with storing the 23 bits of the mantissa? And, I mustn't use functions like strtoul
that convert the 32-bit number directly into binary. I have to use formula
.
推荐答案
鉴于所有的公式和示例编号以及一个计算器,以下代码的哪一部分难以正确?
Which part of the below code was hard to get right given all the formulas and sample numbers and a calculator?
#include <stdio.h>
#include <limits.h>
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned uint32;
#else
typedef unsigned long uint32;
#endif
#define C_ASSERT(expr) extern char CAssertExtern[(expr)?1:-1]
// Ensure uint32 is exactly 32-bit
C_ASSERT(sizeof(uint32) * CHAR_BIT == 32);
// Ensure float has the same number of bits as uint32, 32
C_ASSERT(sizeof(uint32) == sizeof(float));
double Ieee754SingleDigits2DoubleCheat(const char s[32])
{
uint32 v;
float f;
unsigned i;
char *p1 = (char*)&v, *p2 = (char*)&f;
// Collect binary digits into an integer variable
v = 0;
for (i = 0; i < 32; i++)
v = (v << 1) + (s[i] - '0');
// Copy the bits from the integer variable to a float variable
for (i = 0; i < sizeof(f); i++)
*p2++ = *p1++;
return f;
}
double Ieee754SingleDigits2DoubleNoCheat(const char s[32])
{
double f;
int sign, exp;
uint32 mant;
int i;
// Do you really need strto*() here?
sign = s[0] - '0';
// Do you really need strto*() or pow() here?
exp = 0;
for (i = 1; i <= 8; i++)
exp = exp * 2 + (s[i] - '0');
// Remove the exponent bias
exp -= 127;
// Should really check for +/-Infinity and NaNs here
if (exp > -127)
{
// Normal(ized) numbers
mant = 1; // The implicit "1."
// Account for "1." being in bit position 23 instead of bit position 0
exp -= 23;
}
else
{
// Subnormal numbers
mant = 0; // No implicit "1."
exp = -126; // See your IEEE-54 formulas
// Account for ".1" being in bit position 22 instead of bit position -1
exp -= 23;
}
// Or do you really need strto*() or pow() here?
for (i = 9; i <= 31; i++)
mant = mant * 2 + (s[i] - '0');
f = mant;
// Do you really need pow() here?
while (exp > 0)
f *= 2, exp--;
// Or here?
while (exp < 0)
f /= 2, exp++;
if (sign)
f = -f;
return f;
}
int main(void)
{
printf("%+g
", Ieee754SingleDigits2DoubleCheat("110000101100010010000000000000000"));
printf("%+g
", Ieee754SingleDigits2DoubleNoCheat("010000101100010010000000000000000"));
printf("%+g
", Ieee754SingleDigits2DoubleCheat("000000000100000000000000000000000"));
printf("%+g
", Ieee754SingleDigits2DoubleNoCheat("100000000100000000000000000000000"));
printf("%+g
", Ieee754SingleDigits2DoubleCheat("000000000000000000000000000000000"));
printf("%+g
", Ieee754SingleDigits2DoubleNoCheat("000000000000000000000000000000000"));
return 0;
}
输出(ideone):
-98.25
+98.25
+5.87747e-39
-5.87747e-39
+0
+0
这篇关于如何将 IEEE 754 单精度二进制浮点数转换为十进制数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!