8

如何在 C中打印(即到标准输出)一个浮点数,而不在传递给 printf 时将其提升为双精度值?

这里的问题是 C 中的可变参数函数将所有float参数提升为double,这会导致两次不必要的转换。例如,如果在 GCC 中打开-Wdouble-promotion并编译

float f = 0.f;
printf("%f", f);

你会得到

warning: implicit conversion from 'float' to 'double' when passing argument to function

我的处理能力相对较小(72MHz ARM Cortex-M3),而且我肯定在浮点数据的 ASCII 输出上遇到瓶颈。由于该架构一开始就缺乏硬件 FPU,因此必须在单精度和双精度之间进行转换并无济于事。

有没有办法在直 C 中更有效地打印浮点数?

4

4 回答 4

9

避免升级不会为您节省任何东西,因为内部double(或更可能long double)算术printf将执行将消耗至少 1000 倍的时间。准确打印浮点值并不容易

如果您不关心准确性,并且只需要快速打印近似值,您可以滚动自己的循环来进行打印。只要您的值不是太大而无法放入整数类型,首先将非小数部分转换并打印为整数,然后将其减去并循环乘以 10 并取出整数部分以打印小数部分一次一个数字(将其缓冲在一个字符串中以获得更好的性能)。

或者你可以这样做:

printf("%d.%.6d", (int)x, (int)((x-(int)x)*1000000));
于 2011-04-02T14:17:10.097 回答
5

不幸的是,printf不支持处理普通的 float:s。

这意味着您必须编写自己的打印函数。如果您不需要 的全部表达能力printf,您可以轻松地将浮点值转换为整数部分和表示小数位数的部分,并使用整数打印出来。

另一方面,如果您只是想摆脱警告,则可以显式地floatdouble.

于 2011-04-02T08:21:42.520 回答
2

我认为这没关系 - printf 已经是一件非常耗时的讨厌的事情,那些转换应该无关紧要。将 float 转换为 double 的时间应该远远少于将任何数字转换为 ascii 的时间(您应该/可以分析您的代码以获得明确的答案)。唯一剩下的解决方案是编写一个自己的自定义输出例程,它转换 float->ascii 然后使用 puts (或类似的)。

于 2011-04-02T08:29:08.853 回答
0
  • 第一种方法:使用 ftoa 而不是 printf。轮廓。

  • 为了增加输出的灵活性,我会进入编译器的 stdlib 的源代码,无论如何可能是 gcc 的一些衍生物,找到 printf 实现并复制相关代码以进行 double -> ascii 转换。将其重写为 float -> ascii。

  • 接下来,手动将一个或两个重要的调用站点更改为您的新(非可变)版本并对其进行配置。

  • 如果它解决了你的问题,你可以考虑重写你自己的 printf,基于 stdlib 的版本,而不是 float 你传递 float*。那应该摆脱自动升级。

于 2011-04-02T09:13:40.523 回答