C/C++ 下完全复刻 Python print("%s", floatnum) 好像有点难

79 天前
 nealot
$ cat test.c
#include <stdio.h>

void main()
{
    double v = 1.38;
    printf("%lf\n", v);
    printf("%.17g\n", v);
}

$ gcc test.c -o test
$ ./test
1.380000
1.3799999999999999

$ python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> v = 1.38
>>> print("%s" % v)
1.38

需求很简单:我要在 C/C++ 中打印浮点数时,像 Python "%s" % v 那样打印,只打印必要的小数点后内容

Stack Overflow 上有一篇讨论

https://stackoverflow.com/questions/16839658/printf-width-specifier-to-maintain-precision-of-floating-point-value

建议使用 printf("%.17g", number) 但是测试后发现它不工作

简单翻了一些资料,似乎 %.17g 的数字要达到 17 确实是有必要的

(我的系统是 Ubuntu 22.04 / x86_64)

1362 次点击
所在节点    程序员
8 条回复
aiqinxuancai
79 天前
c++20 的 std::format
cwxiaos
79 天前
有 Python-like 的 print 库的

https://ufile.io/lp2v1gb8
cwxiaos
79 天前
```
#include <stdio.h>
#include "print.h"

int main(int argc, char** agrv){
float num_1 = 1.38;
int num_2 = 1;
double num_3 = 3.22230001;
print("Num1:", num_1, "Num2:", num_2, "Num3:", num_3);

return 0;
}
```

Debian 12 /x86_64 下:

```
Num1: 1.38 Num2: 1 Num3: 3.2223
```

在 C++下用 C++的 API, C 下面也可以使用%g

```
#include <stdio.h>
#include "print.h"

int main(int argc, char** agrv){
float num = 1.38;
printf("%g\n", num);

return 0;
}
```

打印

```
1.38
```
nealot
79 天前
%g 应该是正解

stackoverflow 上票数第二高的答案,煞有介事地介绍要用 %.17g ...

%.17g 确实达到了 double 地精度上界了,而且其实 %.17g 在不少情况下工作是正常的,估计 stackoverflow 上的回答者没有仔细测试就把方案发出来了
cwxiaos
79 天前
@nealot %g 不是,我试了下,数字大了会跳成科学计数法,还是用现成库吧
icyalala
79 天前
cwxiaos
79 天前
%.15g 可以,这个应该和浮点误差有关,1.38 恰好在 17 位有个 1,所以打了出来
```
double num1 = 123.456;
double num2 = 78.9;
double num3 = 12345.6789;
double num4 = 1.38;
```

输出

```
123.456
78.9
12345.6789
1.38
```

合理选择位数,避免浮点误差导致的多出来的数就行了
cnbatch
79 天前
如果你的编译器支持 C++20 ,用内置的 format 即可:
https://coliru.stacked-crooked.com/a/56cb3388b1c85629

```
#include <format>
#include <iostream>


int main()
{
double v = 1.38;
std::cout << std::format("{}\n", v);
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1016993

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX