Tôi đề xuất @Jens Gustedt giải pháp thập lục phân: sử dụng% a.
OP muốn “in với độ chính xác tối đa (hoặc ít nhất đến số thập phân quan trọng nhất)”.
Một ví dụ đơn giản sẽ là in một phần bảy như trong:
#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01
Nhưng hãy tìm hiểu sâu hơn ...
Về mặt toán học, câu trả lời là "0,142857 142857 142857 ...", nhưng chúng tôi đang sử dụng số dấu phẩy động có độ chính xác hữu hạn. Hãy giả sử IEEE 754 nhị phân chính xác kép . Vì vậy, OneSeventh = 1.0/7.0
kết quả trong giá trị dưới đây. Cũng được hiển thị là các double
số dấu phẩy động có thể biểu diễn trước và sau .
OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375
Việc in biểu diễn thập phân chính xác của a double
bị hạn chế sử dụng.
C có 2 họ macro <float.h>
để giúp chúng tôi.
Tập hợp đầu tiên là số chữ số có nghĩa cần in trong một chuỗi ở dạng thập phân nên khi quét lại chuỗi, chúng ta nhận được dấu phẩy động ban đầu. Được hiển thị với giá trị tối thiểu của thông số C và một trình biên dịch C11 mẫu .
FLT_DECIMAL_DIG 6, 9 (float) (C11)
DBL_DECIMAL_DIG 10, 17 (double) (C11)
LDBL_DECIMAL_DIG 10, 21 (long double) (C11)
DECIMAL_DIG 10, 21 (widest supported floating type) (C99)
Bộ thứ hai là số chữ số có nghĩa mà một chuỗi có thể được quét thành dấu phẩy động và sau đó FP được in ra, vẫn giữ nguyên cách trình bày chuỗi đó. Được hiển thị với giá trị tối thiểu của thông số C và một trình biên dịch C11 mẫu . Tôi tin rằng có sẵn trước C99.
FLT_DIG 6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)
Tập hợp các macro đầu tiên dường như đáp ứng mục tiêu của OP là các chữ số có nghĩa . Nhưng macro đó không phải lúc nào cũng có sẵn.
#ifdef DBL_DECIMAL_DIG
#define OP_DBL_Digs (DBL_DECIMAL_DIG)
#else
#ifdef DECIMAL_DIG
#define OP_DBL_Digs (DECIMAL_DIG)
#else
#define OP_DBL_Digs (DBL_DIG + 3)
#endif
#endif
"+ 3" là mấu chốt của câu trả lời trước đây của tôi. Nó tập trung vào việc nếu biết chuỗi chuyển đổi khứ hồi-FP-string (bộ # 2 macro có sẵn C89), làm cách nào để xác định các chữ số cho FP-string-FP (bộ số 1 macro có sẵn bài C89)? Nói chung, thêm 3 là kết quả.
Bây giờ có bao nhiêu chữ số có nghĩa để in đã được biết và định hướng qua <float.h>
.
Để in N chữ số thập phân có nghĩa, người ta có thể sử dụng nhiều định dạng khác nhau.
Với "%e"
, trường độ chính xác là số chữ số sau chữ số chính và dấu thập phân. Theo - 1
thứ tự cũng vậy. Lưu ý: Đây -1
không phải là phần đầuint Digs = DECIMAL_DIG;
printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01
Với "%f"
, trường độ chính xác là số chữ số sau dấu thập phân. Đối với một số như vậy OneSeventh/1000000.0
, người ta sẽ cần OP_DBL_Digs + 6
phải xem tất cả các chữ số có nghĩa .
printf("%.*f\n", OP_DBL_Digs , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285
Lưu ý: Nhiều người đang sử dụng "%f"
. Điều đó hiển thị 6 chữ số sau dấu thập phân; 6 là mặc định hiển thị, không phải là độ chính xác của số.