使用 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.0
和 78871234510124576.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
表示数值。所以,读取数据文件时,相关信息已经丢失
我有以下代码
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.0
和 78871234510124576.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
表示数值。所以,读取数据文件时,相关信息已经丢失