gpt4 book ai didi

java - Java 的 C 兼容 printf 输出

转载 作者:搜寻专家 更新时间:2023-11-01 01:13:39 24 4
gpt4 key购买 nike

我想在 Java 和 C 中将 float/double 转换为字符串,这样输出既一致用户友好

所谓“用户友好”,我的意思是该字符串应该是人类可读且合理的:有效数字的最大数量,以及在适当时自动切换为科学记数法( double 可以跨越所有有效范围)。

我所说的“一致”是指字符串在 Java 和 C 中应该完全相同(如果它们真的很少见,我会容忍一些异常(exception))。

为什么不简单地使用一些 printf 格式字符串,如 "%.5g"?那行得通……差不多。但遗憾的是,精度字段的含义在 Java 和 C 中完全是 different。此外,从 - 到科学计数法的转换不是很一致,甚至格式本身也不是(指数的 2 或 3 位数字......)。不同的 C 编译器有时会产生不同的结果。

"%.5g" 的差异示例

double                  Java %.5g         gcc %.5g      tcc %.5g
1234.0 1234.0 1234 1234
123.45678 123.46 123.45678 123.46
0.000123456 0.00012346 0.00012346 0.00012346
0.000000000000123456 1.2346e-13 1.2346e-13 1.2346e-013

我可以用 C 或 Java(或两者)编写函数代码,但我想知道是否有人已经处理过这个问题。我不太关心性能,但很关心跨 C 编译器的可移植性。

最佳答案

如果您真的想要以 10 为基数的浮点输出,最简单的方法可能是在此处为 C 的 printf 编写 JNI 包装器。 Java 人员决定他们需要自己执行 printf。除了您已经注意到的 %g 之外,他们还决定以一种奇怪的方式更改舍入行为和截断输出。即:

System.out.printf("%.5g\n", 1.03125);
System.out.printf("%.5g\n", 1.09375);
1.0313
1.0938

gcc 正确舍入为偶数:

printf("%.5g\n", 1.03125);
printf("%.5g\n", 1.09375);
1.0312
1.0938

请注意,1.03125 和 1.09375 可以精确表示为 double 值,因为 1/32 = 0.3125。

Java 的 printf %g 格式错误地截断了它的输出:

double d = 1;
for (int i = 0; i < 1035; i++) d /= 2;
System.out.printf("%.20g\n%.20a\n", d, d);
2.7161546124360000000e-312
0x0.00080000000000000000p-1022

正确答案如下:

double d = 1;
for (int i = 0; i < 1035; i++) d /= 2;
printf("%.20g\n%.20a\n", d, d);
2.7161546124355485633e-312
0x0.00080000000000000000p-1022

1.0e-200 是正常的但不能完全表示。 Java 假装没有注意到:

System.out.printf("%.20g\n%.20a\n", 1.0e-200, 1.0e-200);
1.0000000000000000000e-200
0x1.87e92154ef7ac0000000p-665

正确答案如下:

printf("%.20g\n%.20a\n", 1.0e-200, 1.0e-200);
9.999999999999999821e-201
0x1.87e92154ef7ac0000000p-665

因此,您要么不得不忍受 printf 中奇怪的舍入行为,要么您依赖于 gccglibc 的工作。我不建议尝试自己打印 float 。或者您可以只使用 %a,据我所知,它在 Java 中工作得非常好。

关于java - Java 的 C 兼容 printf 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13749802/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com