Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double to String using Java standards

Tags:

java

core

I have the below code

  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);

The double Value which I set is not returned as output.

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

Is there a standard way to convert a Double to a String without explicit type casting with the range of value being long data type (max value) instead of double?

My Intention of asking this question is because am reading an excel sheet using Apache POI with all cell type being general in the Excel. I am using getNumericCellValue() to read the value of a cell which always returns number in decimal format. For example 222 will be returned as 22.0. I want to remove the decimal and convert it to a String.

like image 816
user2918673 Avatar asked Apr 13 '16 08:04

user2918673


2 Answers

Essentially, the root cause of your issue is when you get the double from POI:

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

There, cellValue would already have the same internal representation for both 78871234510124568.0 and 78871234510124576.0 (and at least all numbers inbetween):

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

Output:

4859809850462277474
4859809850462277474

This is simply a matter of how floating point values are stored in memory. There are just not enough bits available to distinguish between these numbers. See What Every Computer Scientist Should Know About Floating-Point Arithmetic and IEEE floating point for more information.

If you need a higher accuracy, you must retrieve the value as a String and then use the String for further processing, like parsing it into a BigDecimal:

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

You need to consider the proper locale, so that the decimal point is treated correctly (. vs. ,). Locale.US uses ..

like image 54
Andreas Fester Avatar answered Sep 24 '22 11:09

Andreas Fester


When you convert a large number to a double you will lose some information. You can only put back that information if your either

  • make assumptions about what the error is. e.g. rounding to 2 decimal places.
  • you know what the error is.

One way this is done with doubles is to have two doubles. One with the main values and one with the error.

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);

prints

cellValue=7.8871234510124576E16 err=-8.0 original=78871234510124568
like image 33
Peter Lawrey Avatar answered Sep 20 '22 11:09

Peter Lawrey