使用 Java 标准将字符串加倍

Double to String using Java standards

我有以下代码

  double cellValue = 78871234510124568.0;

  String cell = new BigDecimal(cellValue).toPlainString(); 
  String b = String.format("%.0f", cellValue);

  System.out.println("Double Value using Big Decimal " + cell);
  System.out.println("Double Value using String format " + b);

我设置的双精度值没有作为输出返回。

Double Value using Big Decimal 78871234510124576
Double Value using String format 78871234510124576

是否有一种标准方法可以将 Double 转换为 String 而无需显式类型转换,值的范围是 long 数据类型(最大值)而不是 double?

我问这个问题的目的是因为我正在使用 Apache POI 阅读 excel sheet,其中所有单元格类型在 Excel 中都是通用的。我正在使用 getNumericCellValue() 读取一个单元格的值,该单元格总是 returns 十进制格式的数字。例如 222 将返回为 22.0。我想删除小数并将其转换为字符串。

您可以使用以下内容:

DecimalFormat amountFormatter = new DecimalFormat("############");
String s = amountFormatter.format(amount.doubleValue());

当您将大数字转换为 double 时,您会丢失一些信息。如果您

  • 假设错误是什么。例如四舍五入到小数点后两位。
  • 你知道错误是什么。

用双打完成的一种方法是有两个双打。一个是主要值,一个是错误。

long l = 78871234510124568L;
double cellValue = l;
double err = l - (long) cellValue;

long original = (long) cellValue + (long) err;

System.out.println("cellValue="+cellValue+" err="+err+" original="+original);

打印

cellValue=7.8871234510124576E16 err=-8.0 original=78871234510124568

本质上,问题的根本原因是当您从 POI 获得 double 时:

Cell myCell = ... ;
double cellValue = myCell.getNumericCellValue();

那里,cellValue 已经对 78871234510124568.078871234510124576.0 具有相同的内部表示(至少中间的所有数字):

System.err.println(Double.doubleToRawLongBits(78871234510124568.0));
System.err.println(Double.doubleToRawLongBits(78871234510124576.0));

输出:

4859809850462277474
4859809850462277474

这只是浮点值如何存储在内存中的问题。只是没有足够的位来区分这些数字。 有关详细信息,请参阅 What Every Computer Scientist Should Know About Floating-Point Arithmetic and IEEE floating point

如果您需要更高的准确度,您必须将值检索为 String,然后使用 String 进行进一步处理,例如将其解析为 BigDecimal:

Cell myCell = ... ;
String cellValue = myCell.getStringCellValue();
DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.US);
df.setParseBigDecimal(true);
BigDecimal value = (BigDecimal) df.parse(cellValue);

您需要考虑适当的语言环境,以便正确处理小数点(.,)。 Locale.US 使用 ..

由于您要处理的精度(重要的小数位)如此之多,因此您需要避免使用 Double

所以,首先你应该检查单元格内容是否真的有那么多小数位。 (取决于输入值的方式。)

如果是,那么您需要从 POI 中获取字符串表示并直接使用它,或者将字符串值提供给 BigDecimal 以获取数值。

如果您不能将 POI 排列为 return 高精度值作为字符串,您可能无法成功使用 POI,因为它在内部使用 double 表示数值。所以,读取数据文件时,相关信息已经丢失