Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中打印浮点,同时避免变量参数升级为双精度_C_Floating Point_Printf_Promotions - Fatal编程技术网

在C中打印浮点,同时避免变量参数升级为双精度

在C中打印浮点,同时避免变量参数升级为双精度,c,floating-point,printf,promotions,C,Floating Point,Printf,Promotions,如何在C中打印(即,到stdout)一个浮点,而不在传递到printf时将其提升为double 这里的问题是,C中的变量函数将所有浮点参数提升为双精度,这会导致两个不必要的转换。例如,如果在GCC中打开-Wdouble promotion并编译 float f = 0.f; printf("%f", f); 你会得到 warning: implicit conversion from 'float' to 'double' when passing argument to function

如何在C中打印(即,到stdout)一个浮点,而不在传递到printf时将其提升为double

这里的问题是,C中的变量函数将所有浮点参数提升为双精度,这会导致两个不必要的转换。例如,如果在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直接打印浮点值?

不幸的是,
printf
不支持处理普通浮点值:s

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


另一方面,如果您只是想摆脱警告,您可以显式地将
浮点
转换为
双精度

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

  • 第一种方法:使用ftoa而不是printf。个人资料

  • 为了提高输出灵活性,我将深入研究编译器stdlib的源代码,可能是gcc的一些派生代码,找到printf实现并复制相关代码进行双->ascii转换。将其重写为float->ascii

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

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


    • 避免升级不会为您节省任何东西,因为内部
      双精度
      (或者更可能
      长双精度
      )算法
      printf
      将花费至少1000倍的时间。准确打印浮点值并不容易

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

      或者你可以这样做:

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

      我不同意。浮点到ascii转换中最昂贵的部分是除以10。如果使用浮点运算而不是双精度运算,这些运算速度会更快。@edgar:当然,涉及浮点运算的成本比浮点运算的成本高出一倍。但是div by 10的实现取决于lib的实现。您也可以使用整数运算处理尾数位以获得数字。这在很大程度上取决于所使用的libc(用于嵌入式的libc通常不是一个完整的大型实现)。这就是为什么我说你需要一个明确的答案。唯一可以避免的方法是编写自己的函数。我意识到我需要打印的大多数浮点值都在[0,1]的范围内,所以我可以缩放这些值,然后将它们四舍五入为整数进行打印。这个性能提高了很多。如果有人遇到这个问题,我就只需Base64的数据,并且解码/格式化/漂亮地打印主机上的所有东西。我还考虑了Boo::因果报应,但这将需要C++,而且很有可能它不会节省我的代码大小。