提问人:k314159 提问时间:6/30/2023 更新时间:7/4/2023 访问量:77
格式化以尽可能高的精度进行加倍
Formatting doubles with highest possible precision
问:
像 0.1 这样的数字不能用二进制浮点数精确表示,所以我想以尽可能高的精度打印出来。我知道 64 位类型只能提供高达 15 位左右的有意义的精度,但更多的数字会揭示浮点近似值和实际值之间的差异。double
但是,具有高精度规范的格式(例如仍然没有给我):"%.50f"
String.format("%.50f", 0.1) --> "0.10000000000000000000000000000000000000000000000000"
new BigDecimal(0.1).toString() --> "0.1000000000000000055511151231257827021181583404541015625"
有没有办法在不使用的情况下将数字输出为字符串?BigDecimal
答:
3赞
Joop Eggen
6/30/2023
#1
由于最后一个有意义的数字可以向上或向下舍入,因此不能只在它后面粘上 00...00 (99...99)。
因此,由于在大约 15 个奇数之后仍然存在近似误差,因此是合适的解决方案。您可以假设实际精度为 14 或更低,然后添加零。但仍然给出假新闻。new BigDecimal("...")
printf/format
3赞
k314159
7/4/2023
#2
只是为了添加另一个更详细的答案:
“%f”格式专门记录在小数点后添加 0:
...可以附加零以达到精度。对于规范 表示值,请使用 Float.toString(float) 或 Double.toString(double) (视情况而定)。
Double.toString 记录为使用以下逻辑返回近似值:
m 或 a 的小数部分必须打印多少位数字? 必须至少有一位数字来表示小数部分,并且 除此之外,只要需要多少,但只能多一些数字 唯一区分参数值与相邻类型的值 双。
因此,为了获得二进制浮点值所代表的 String 表示形式,Java 似乎提供了 BigDecimal 作为唯一的选择。
上一个:浮点数学坏了吗?
评论
toString()
double
printf("%.100g", 0.1)
0.1000000000000000055511151231257827021181583404541015625
"0.10000000000000000000000000000000000000000000000000"
0
BigDecimal
在这里给出了正确的存储值 (0xCCCCCCCCCCCCD * 2^-55)。你有什么理由不想使用它吗?因为AFAICT,任何解决方案基本上都相当于重新发明了格式化程序。BigDecimal
System.out.printf("%.30f", new Scanner(System.in).nextDouble());