2011-01-10 29 views
9

Tôi có vấn đề về hệ thống dựa trên UNIX sprintf không làm tròn giá trị đúng.Sự khác biệt làm tròn trên Windows và hệ thống dựa trên Unix trong sprintf

Ví dụ

double tmp = 88888888888885.875 
char out[512]; 

Thats 88,888,888,888,885.875 chỉ để được dễ dàng hơn trên mắt. Tôi đưa ra ví dụ cụ thể và lớn như vậy bởi vì có vẻ như nó hoạt động tốt trên các số nhỏ hơn.

Tôi cố gắng để sử dụng nó trong sau cách

sprintf(out, "%021.2f", tmp); 
printf("out = %s\n", tmp); 

Trên cửa sổ kết quả này trong:

out = 000088888888888885.88 

On ví dụ AIX, nhưng cho thấy trong Linux cũng như:

out = 000088888888888885.87 

Tại sao điều này xảy ra? Bất kỳ ý tưởng và làm thế nào để làm cho nó cư xử tương tự cách trên Win/Unix

Cảm ơn

+2

erm, http://www.ideone.com/UVtft báo cáo '.88', SuseLinux cục bộ của tôi báo cáo tương tự ... – Nim

+3

Bạn đang sử dụng CPU nào cho mỗi hệ điều hành? – chrisaycock

+0

Trên Linux (Debian 5) AMD64 Tôi nhận được '000088888888888885.88' –

Trả lời

1

Có một số bug report cho glibc có vấn đề rất giống với vấn đề của bạn. Kết luận chính (trong chú thích 46) ở đây là gấp đôi không phải là một số có 15 chữ số thập phân và bạn không nên mong đợi nó hoạt động như thế.

Cách giải quyết khác là bạn có thể thêm thứ gì đó nhỏ vào số của mình để làm cho chúng tròn hơn. Nhưng giải pháp này không phải là chung vì nó phụ thuộc vào phạm vi số bạn đối phó với.

workaround khác có thể được nhân để chuẩn bị cho họ làm tròn, sau đó làm tròn (ví dụ 2597.625*100 = 259762.5 -> 259763 = 2597.63*100)

Tuy nhiên tôi nghĩ rằng phải có cách giải quyết thông minh hơn.

+0

Tôi không sử dụng cách giải quyết của bạn nhưng đầu một phần là những gì tôi cần cảm ơn – grobartn

0

Đó là bởi vì bạn đang sử dụng double mà có những hạn chế chính xác, ý nghĩa, bạn 88888888888885.875 có lẽ được làm tròn đến cái gì khác trong nội bộ.

Xem thêm thông tin in a similar question, trong blogs hoặc trong wikipedia.

+3

Có bởi vì đôi khi được làm tròn khác nhau trên các hệ điều hành khác nhau? Tất nhiên nó có những giới hạn về độ chính xác, đó là lý do tại sao anh ta nhận được những câu trả lời khác nhau. – Grammin

+2

Nó có thể khác với kiến ​​trúc của hộp để một số đánh bóng được thực hiện bởi printf của libc. Như bạn có thể thấy từ bình luận cho đến câu hỏi, ngay cả trong cùng một hệ điều hành (Linux) nó hoạt động khác nhau, bởi vì về cơ bản không có bảo hành rằng nó sẽ hành xử giống nhau. –

0

Khi thực hiện tuân thủ IEEE 754, cần in 88888888888885.88 ở chế độ làm tròn mặc định. Điều này không liên quan gì đến độ chính xác của dấu phẩy động vì giá trị là chính xác; nó chỉ đơn giản là vấn đề làm tròn của printf tới 2 vị trí sau dấu thập phân. Không biết tại sao bạn nhìn thấy 88888888888885.87 trên một số hệ thống.

+1

OP có thể muốn bỏ qua 'sprintf' (và chỉ gán trực tiếp cho một đôi) để xác minh rằng điều này đang xảy ra trong' printf'. – Cascabel

1

Đại diện điểm nổi nào được bộ xử lý và trình biên dịch của bạn sử dụng? Không phải tất cả các bộ vi xử lý đều sử dụng cùng một cách để biểu diễn các giá trị dấu phẩy động và thậm chí các trình biên dịch có thể chọn các phương thức biểu diễn dấu phẩy động khác nhau (tôi nghĩ trình biên dịch Microsoft C++ thậm chí có các tùy chọn để chọn biểu diễn).

Trang http://www.quadibloc.com/comp/cp0201.htm cung cấp tổng quan về một số biểu diễn dấu phẩy động (mặc dù chúng dường như là các kiến ​​trúc khá cũ được hiển thị ở đó).

http://msdn.microsoft.com/en-us/library/0b34tf65.aspx mô tả cách Microsoft Visual C++ lưu trữ các giá trị dấu phẩy động. Tôi không thể tìm thấy ngay lập tức những gì đại diện được sử dụng bởi AIX hoặc Linux.

Ngoài ra, mọi trình biên dịch đều có các tùy chọn cho phép bạn chỉ ra cách bạn muốn làm việc với các thao tác dấu phẩy động. Bạn có muốn chúng chính xác nhất có thể (nhưng có thể hơi chậm hơn) không? Hay bạn muốn các hoạt động điểm động nhanh nhất có thể (nhưng có thể kém chính xác hơn)?

+0

MSVC không thể chọn biểu diễn, tùy chọn của nó là về tối ưu hóa nó thực hiện trên số học và phương pháp dấu chấm động. – Puppy

+0

Đây là một câu hỏi thú vị liên quan: http://stackoverflow.com/questions/1961442/different-math-rounding-behaviour-between-linux-mac-os-x-and-windows – mizo

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