在 C 中打印浮点数,同时避免可变参数提升为 double

问题描述 投票:0回答:5

如何在 C 中打印(即到标准输出)float,而不在传递给 printf 时将其提升为 double

这里的问题是 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 中更有效地打印浮点数?

c floating-point printf promotions
5个回答
9
投票

避免升级不会为你节省任何东西,因为内部

double
(或更可能是
long double
)算术
printf
将执行至少 1000 倍的时间。准确打印浮点值并不容易

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

或者你可以这样做:

printf("%d.%.6d", (int)x, (int)((x-(int)x)*1000000));

6
投票

不幸的是,

printf
不支持处理普通浮动:s。

这意味着您必须编写自己的打印函数。如果您不需要

printf
的完整表达能力,您可以轻松地将浮点值转换为整数部分和代表小数位数的部分,并使用整数打印出来。

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

float
转换为
double


2
投票

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


2
投票
  • 第一种方法:使用ftoa代替printf。简介.

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

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

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


0
投票

可能以不好的方式:为 float 变量添加包装器以将它们作为 int32 传递

#define FTI32(val) *((int32_t*)&val)

使用自定义格式化程序库,例如 xformatc.c 编辑浮点部分:

param.dbl = (DOUBLE) va_arg(args, DOUBLE_ARGS);

替换为:

int fint = va_arg(args, int);
param.dbl =  *((float*)(&fint));
© www.soinside.com 2019 - 2024. All rights reserved.