- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想在 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 中奇怪的舍入行为,要么您依赖于 gcc
和 glibc
的工作。我不建议尝试自己打印 float 。或者您可以只使用 %a
,据我所知,它在 Java 中工作得非常好。
关于java - Java 的 C 兼容 printf 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13749802/
我想知道以下语句在 C 中会打印什么? printf("hello\n") || (printf("goodbye\n") || printf("world\n")); 我通常习惯于使用“cout”在
这是我目前正在学习的系统编程类(class)的幻灯片: catch_child 是 SIGCHLD 处理程序。输出与代码如何对应?为什么没有打印一些“Child #x started”消息? 最佳答案
这有点像拼图……我刚刚又回到了C,打算这次掌握它。所以我一直在阅读 The C Programming Language ,我得到了这个声明: Among others, printf also re
如何使用 printf 在字符串末尾附加空格? 我找不到任何在右侧附加空格的示例。 A similar question我发现使用 printf改为在字符串的左侧添加空格。 最佳答案 使用负数左对齐(
我想通过 usart 从 stm32f405 注销。 在我的 syscall.c 文件中,我实现了通过 usart 打印的功能: int _write(int file, char *ptr, int
我想定义一个记录器函数,比如 myPutStrLn = putStrLn . (++) "log: " main = do myPutStrLn "hello" 这很好。现在我想用 printf 格式
Printf module API详细介绍了类型转换标志,其中: %B: convert a boolean argument to the string true or false %b: conv
@H2CO3 这是我的主要代码: #pragma OPENCL EXTENSION cl_ amd_ printf : enable #define PROGRAM_FILE "matvec.cl"
Printf module API详细介绍了类型转换标志,其中: %B: convert a boolean argument to the string true or false %b: conv
您可以使用 printf 字段宽度说明符截断字符串: printf("%.5s", "abcdefgh"); > abcde 不幸的是,它不适用于数字(将 d 替换为 x 是相同的): printf(
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 4 年前。 Improve th
我遇到了我见过的最奇怪的错误之一。 我有一个简单的程序,可以打印多个整数数组。 对数组进行排序,然后打印...... place_in_buf(n100, 100); insertion(10
我的程序是每隔一段时间获取文件大小并显示它以记录任何更改。由于某种原因,执行下面的代码挂起,只为我提供了一个光标。没有打印或显示任何内容。 代码: #include #include #inclu
printf("It is currently %s's turn.\n", current->name); 我想知道为什么在 %s 之后打印出额外的换行符。我知道C 中的字符串总是以\0 结尾。没有
这个问题已经有答案了: printf anomaly after "fork()" (3 个回答) fork() in c using printf [duplicate] (2 个回答) 已关闭 9
我对编程很陌生。 我正在尝试编写一个程序,从数组中调用水果的价格。但我希望代码在写价格之前也写水果的名称。如果我键入 2,如何使输出为“Orange price : 10”而不仅仅是 price :
这个问题在这里已经有了答案: How do I print a non-null-terminated string using printf? (2 个答案) 关闭 7 年前。 例如,我有一个字符
我有一个 atmel UC3-L0 和罗盘传感器。现在我安装 AtmelStudio 并将一些演示代码下载到电路板中。但是我不知道演示代码中的函数 printf 会在哪里出现数据。我应该如何获取数据?
我有一个 atmel UC3-L0 和罗盘传感器。现在我安装 AtmelStudio 并将一些演示代码下载到电路板中。但是我不知道演示代码中的函数 printf 会在哪里出现数据。我应该如何获取数据?
嗨,我是 C 世界的新手,我的代码确实有些奇怪。目标是创建一个函数,可以在开头和结尾处用空格和/或制表符修剪字符串。我无法使用字符串库。 问题是我的代码中有一个 printf 只是用于测试,它的工作非
我是一名优秀的程序员,十分优秀!