2016-04-13 17 views
6

Tôi có đoạn code dưới đâyđúp để Chuỗi sử dụng tiêu chuẩn Java

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

Giá trị tăng gấp đôi mà ta đã đặt không được trả lại như đầu ra.

Gấp đôi giá trị sử dụng Big Decimal 78871234510124576
Gấp đôi giá trị sử dụng định dạng chuỗi 78871234510124576

Có một cách tiêu chuẩn để chuyển đổi một Double đến một String mà không rõ ràng loại đúc với khoảng giá trị là long dữ liệu loại (giá trị lớn nhất) thay vì double?

Ý định của tôi về việc đặt câu hỏi này là vì tôi đang đọc một bảng tính excel bằng cách sử dụng Apache POI với tất cả các loại tế bào là chung trong Excel. Tôi đang sử dụng getNumericCellValue() để đọc giá trị của một ô luôn trả về số ở định dạng thập phân. Ví dụ 222 sẽ được trả lại là 22.0. Tôi muốn loại bỏ các số thập phân và chuyển đổi nó thành một chuỗi.

+3

Chỉ cần tự hỏi: mẫu "% f" có thực sự hoạt động trên Chuỗi là đầu vào không? Mục đích là gì bằng cách chuyển một số thành một chuỗi; sau đó định dạng chuỗi đó thành số? – GhostCat

+4

Đối với java, '78871234510124568.0' và' 78871234510124576' là cùng một số, bởi vì một đôi không đủ lớn để lưu trữ rất nhiều số thập phân chính xác như vậy – Ferrybig

+0

Ý định của tôi đặt câu hỏi này là vì tôi đang đọc một bảng excel bằng cách sử dụng apache POI ... với tất cả các loại tế bào được nói chung trong Excel.am bằng cách sử dụng getNumericCellValue() để đọc giá trị của một tế bào ... mà luôn luôn trả về số ở định dạng thập phân Ví dụ 222 sẽ được trả lại là 22.0 ... Tôi muốn loại bỏ thập phân và chuyển đổi nó đến một chuỗi – user2918673

Trả lời

1

Với nhiều bit chính xác (số thập phân đáng kể) bạn đang cố xử lý, bạn cần tránh sử dụng Double.

Vì vậy, trước tiên, bạn nên kiểm tra nội dung ô có nhiều vị trí thập phân hay không. (Phụ thuộc vào cách nhập giá trị.)

Nếu có, thì bạn sẽ cần lấy một biểu diễn chuỗi từ POI và sử dụng trực tiếp hoặc nạp giá trị Chuỗi vào BigDecimal để nhận giá trị số.

Nếu bạn không thể sắp xếp POI trả về giá trị độ chính xác cao dưới dạng Chuỗi, bạn có thể không sử dụng POI thành công vì nó đại diện cho giá trị số sử dụng double nội bộ. Tus, thông tin liên quan đã bị mất khi đọc tệp dữ liệu.

0

Bạn có thể sử dụng như sau:

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

Đặt ra sẽ là 78871234510124576.00 Nhưng tôi muốn nó được 78871234510124568 là nó bởi vì như vậy một giá trị lớn sẽ không được hỗ trợ bởi đôi ?? – user2918673

+0

Tôi đã chỉnh sửa, hãy kiểm tra. – KayV

+0

Không #Karan Verma – user2918673

2

Khi bạn chuyển đổi một số lượng lớn để một double bạn sẽ mất một số thông tin. Bạn chỉ có thể trả lại thông tin đó nếu một trong các số

  • giả định về lỗi đó. ví dụ. làm tròn đến 2 chữ số thập phân.
  • bạn biết lỗi là gì.

Một cách này được thực hiện với đôi là có hai đôi. Một với các giá trị chính và một với lỗi.

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

in

cellValue=7.8871234510124576E16 err=-8.0 original=78871234510124568 
4

Về cơ bản, các nguyên nhân gốc rễ của vấn đề của bạn là khi bạn nhận được double từ POI:

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

Có, cellValue sẽ đã có các đại diện nội bộ tương tự cho cả hai 78871234510124568.078871234510124576.0 (và ít nhất là tất cả các số giữa):

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

Output:

4859809850462277474 
4859809850462277474 

này chỉ đơn giản là một vấn đề như thế nào giá trị dấu chấm động được lưu trữ trong bộ nhớ. Chỉ có không có đủ bit để phân biệt giữa những con số này. Xem What Every Computer Scientist Should Know About Floating-Point ArithmeticIEEE floating point để biết thêm thông tin.

Nếu bạn cần một độ chính xác cao hơn, bạn phải lấy giá trị như một String và sau đó sử dụng String để chế biến tiếp, như phân tích nó thành một BigDecimal:

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

Bạn cần phải xem xét các địa phương thích hợp, để dấu thập phân được xử lý chính xác (. so với ,). Locale.US sử dụng ..

Các vấn đề liên quan