2009-04-14 37 views
14

Ý nghĩa chính xác của numeric_limits :: digits10 là gì? Một số câu hỏi liên quan khác trong stackoverflow khiến tôi nghĩ rằng đó là độ chính xác tối đa của một đôi, nhưngÝ nghĩa của numeric_limits <double> :: digit10

  • Nguyên mẫu sau bắt đầu làm việc (những thành công là đúng) khi độ chính xác lớn mà 17 (== 2 + numeric_limits :: digits10)
  • Với STLPort, readDouble == vô cùng ở cuối; với STL của microsoft, readDouble == 0.0.
  • Nguyên mẫu này có ý nghĩa gì không :)?

Đây là nguyên mẫu:

#include <float.h> 
#include <limits> 
#include <math.h> 
#include <iostream> 
#include <iomanip> 
#include <sstream> 
#include <string> 
int main(int argc, const char* argv[]) { 
    std::ostringstream os; 
    //int digit10=std::numeric_limits<double>::digits10; // ==15 
    //int digit=std::numeric_limits<double>::digits; // ==53 
    os << std::setprecision(17); 
    os << DBL_MAX; 
    std::cout << os.str(); 
    std::stringbuf sb(os.str()); 
    std::istream is(&sb); 
    double readDouble=0.0; 
    is >> readDouble; 
    bool success = fabs(DBL_MAX-readDouble)<0.1; 
} 
+0

liên quan: [chính xác thập phân phao] (http://stackoverflow.com/questions/3310276/decimal-precision-of-floats) và [Is it 6 or 7.22?] (ht tp: //stackoverflow.com/q/30688422/183120). – legends2k

Trả lời

8

numeric_limits :: digits10 xác định số chữ số thập phân ở bên trái dấu thập phân đại diện cho bạn có thể mà không mất độ chính xác. Mỗi loại sẽ có một số khác nhau của các giá trị thập phân có thể biểu diễn.

+0

nó không có nghĩa là số có thể chứa 15 chữ số sau số thập phân nếu không có số nào trừ 0 trước dấu chấm? – Guillaume07

+0

Câu trả lời này không đúng. Xem [tại đây] (http://stackoverflow.com/a/13103444/183120). – legends2k

6

'53' là chiều rộng bit của significand mà loại của bạn (đôi) giữ. '15' là số của số thập phân chữ số có thể được biểu diễn an toàn với loại chính xác đó.

14

numeric_limits::digits10 là số chữ số thập phân có thể được giữ mà không bị mất.

Ví dụ numeric_limits<unsigned char>::digits10 là 2. Điều này có nghĩa là một thẻ không dấu có thể giữ 0,99 mà không bị mất. Nếu thì đó là 3 nó có thể giữ 0..999, nhưng như chúng ta đều biết nó chỉ có thể giữ 0..255.

This manual page có một ví dụ cho số dấu chấm động, trong đó (khi rút ngắn) cho thấy

cout << numeric_limits<float>::digits10 <<endl; 
float f = (float)99999999; // 8 digits 
cout.precision (10); 
cout << "The float is; " << f << endl; 

in

6 
The float is; 100000000 
+0

Tại sao có 8 chữ số thay vì 7 trong ví dụ nổi, bởi vì nó có thể đủ để hiển thị vấn đề? Có lý do nào khác đằng sau chuyện này không? – Guillaume07

+1

@ Guillaume07 Theo như tôi có thể nói, tất cả 7 số * toàn bộ * số tồn tại nguyên vẹn "đôi-> float-> đôi" chuyển đổi. Số nguyên nhỏ nhất không thành công là 16777217, có 8 chữ số. Giải thích lý do tại sao number_limits :: digit10 là 6 có thể được tìm thấy tại đây http://stackoverflow.com/questions/3310276/decimal-precision-of-floats –

6

Xem giấy rất dễ đọc này: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2005.pdf

Mặc dù DBL_MAX (= std :: numeric_limits :: digit10 = 15 chữ số) là số lượng chữ số được đảm bảo tối thiểu cho số lần tăng gấp đôi e, giá trị DBL_MAXDIG10 (= 17 chữ số) được đề xuất trong bài báo có tính chất hữu ích:

  • Trong số là số lượng tối thiểu của các chữ số cần thiết để tồn tại một khứ hồi mẫu chuỗi và trở lại và nhận được cùng một đôi đến cuối cùng.

  • Là số lượng chữ số tối thiểu cần để chuyển đổi số thành chuỗi và hiển thị các chuỗi khác nhau mỗi khi bạn nhận được (A! = B) trong mã. Với 16 hoặc ít hơn chữ số, bạn có thể nhận được gấp đôi không bằng mã, nhưng khi chúng được chuyển đổi thành dạng chuỗi, chúng giống nhau (trường hợp này sẽ khác nhau khi so sánh với mã, nhưng một tệp nhật ký sẽ hiển thị chúng giống hệt nhau - rất khó hiểu và khó gỡ lỗi!)

Khi bạn so sánh giá trị (ví dụ như bằng cách xem xét chúng bằng tay bằng diff'ing hai tập tin log) chúng ta nên nhớ rằng chữ số 1-15 là luôn luôn hợp lệ, nhưng sự khác biệt trong ngày 16 và 17 chữ số THÁNG được rác.

2

digits10 là dành cho chuyển đổi: string → đôi → chuỗi
max_digits10 là dành cho chuyển đổi: đôi → chuỗi → đôi

Trong chương trình của bạn, bạn đang sử dụng chuyển đổi (double → chuỗi → kép). Bạn nên sử dụng max_digits10 thay vì digits10.


Để biết thêm chi tiết về digits10max_digits10, bạn có thể đọc: