寻找替代snprintf()函数的方法

4
我想将一个浮点数(例如f=1.234)转换为字符数组(例如s="1.234")。使用snprintf()很容易实现,但由于某些大小和性能原因,我不能使用它(它是一个嵌入式平台,其中snprintf()因为在内部使用双精度而太慢了)。
那么问题来了:如何轻松地将浮点数转换为字符数组(正负浮点数,没有指数表示,小数点后最多三位数字)?
谢谢!
PS:为了澄清这一点:该平台配备了一个NEON FPU,可以在硬件上执行32位浮点运算,但对64位双精度有些慢。该平台的C库不幸没有特定的NEON / float变体的snprintf,因此我需要一个替代方案。除此之外,整个snprintf / printf功能会增加太多代码大小。

2
没有“简单”的选择,唯一的替代方案就是自己编写转换代码。这要么非常低效(使用算术运算),要么非常复杂,并且需要你“了解”平台上浮点数的表示方式。 - user2371524
1
如何轻松地将浮点数转换为字符数组?可以使用其他人编写的库。但如果您使用低端嵌入式设备且浮点性能成问题,则可能需要考虑改用整数。 - user694733
2
使用定点数学。例如,数字1.234存储为1234 - user3386109
2
乘以1000,截断为整数,至少使用4个字段宽度打印前导零,将小数点放在末尾的第3位。 - Antti Haapala -- Слава Україні
1
@FelixPalmen,原帖中说(模拟的?)双精度数学运算很慢。 - Antti Haapala -- Слава Україні
显示剩余11条评论
2个回答

2

对于许多微控制器,可以使用不支持浮点/双精度的简化printf函数。例如,许多平台都有newlib nano,德州仪器提供了ustdlib.c

使用其中一个非浮点printf函数,您可以将打印拆分为仅使用整数的内容,例如:

float a = -1.2339f;
float b = a + ((a > 0) ? 0.0005f : -0.0005f);
int c = b;
int d = (int)(b * 1000) % 1000;
if (d < 0) d = -d;
printf("%d.%03d\n", c, d);

输出

-1.234

请注意在8位和16位平台上整数溢出的情况。

-编辑- 此外,根据评论,处理舍入边界情况将提供与printf实现不同的答案。


小心负数:你不想得到“-1.-234”。 - user694733
1
这个变量很好,但仍然使用了巨大的printf()函数——其中包含了比这里使用的% d更多的转换功能。 - Elmi
1
|a/1000| > INT_MAX 时,这将失败。使用 long long 可以帮助减少问题范围。对于接近 x.xxx5 的值,它也经常舍入不正确。 - chux - Reinstate Monica
3
这个答案忽略了浮点数计算中舍入的影响。例如,如果a等于3.0004999637603759765625,则输出为“3.001”,但正确的结果应为“3.000”。请注意修正此问题。 - Eric Postpischil
1
float b = a + ((a > 0) ? 0.0005 : -0.0005); brings in the possibility of double math. Recommend using float constants rather than double ones: float b = a + ((a > 0) ? 0.0005f : -0.0005f); - chux - Reinstate Monica
显示剩余2条评论

0
你可以检查一下你的stdlib是否提供了strfromf,这是一种将float转换为字符串的低级函数,通常由printf和相关函数使用。如果可用,这可能比包含整个stdio lib更轻量级(实际上,这就是60559 C扩展标准中包含它的原因)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接