如何在不使用 C 中的 sprintf 或 ftoa 的情况下将 float / double 转换为 ASCII?
我正在使用嵌入式系统。
最佳答案
您采用的方法取决于可能的值范围。您当然对可能的范围有一些内部知识,并且您可能只对更窄范围内的转化感兴趣。
因此,假设您只对整数值感兴趣。在这种情况下,我只是将数字分配给 int
或 long
,此时问题变得相当明显。
或者,假设范围不包含任何大指数,但您对分数的几位感兴趣。要得到三位数的分数,我可能会说 int x = f * 1000;
,转换 x,然后插入小数点作为字符串操作。
如果没有上述所有条件, float 或 double 有一个符号位、一个分数和一个指数。分数中有一个隐藏的 1
。 (数字被归一化,直到它们没有前导零,此时它们再移动一次以获得额外的精度。)然后数字等于分数(加上前导“1”)* 2 ** 指数.对于基本上所有使用 IEEE 754 表示的系统,您只需使用 this Wikipedia IEEE 754 page了解格式。这与仅转换整数并没有什么不同。
对于单精度,一旦得到指数和分数,数字的值注1就是(frac/223 + 1) * 2exp,或 frac * 2exp - 23 + 2exp。
这是一个可以让您开始进行有用转换的示例:
$ cat t.c
#include <stdio.h>
void xconvert(unsigned frac)
{
if (frac) {
xconvert(frac / 10);
printf("%c", frac % 10 | '0');
}
}
void convert(unsigned i)
{
unsigned sign, exp, frac;
sign = i >> 31;
exp = (i >> (31 - 8)) - 127;
frac = i & 0x007fffff;
if (sign)
printf("-");
xconvert(frac);
printf(" * 2 ** %d + 2 ** %d\n", exp - 23, exp);
printf("\n");
}
int main(void)
{
union {
float f;
unsigned i;
} u;
u.f = 1.234e9;
convert(u.i);
return 0;
}
$ ./a.out
1252017 * 2 ** 7 + 2 ** 30
注意 1. 在这种情况下,分数的转换就像二进制小数点在右边而不是左边一样,然后对指数和隐藏位进行补偿调整。
关于c - 如何在不使用 C 中的 sprintf 或 ftoa 的情况下将 float/double 转换为 ASCII?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2268725/