Điều này không thể được thực hiện với các printf
chỉ định định dạng thông thường . Gần nhất bạn có thể nhận được sẽ là:
printf("%.6g", 359.013); // 359.013
printf("%.6g", 359.01); // 359.01
nhưng ".6" là tổng chiều rộng số nên
printf("%.6g", 3.01357); // 3.01357
phá vỡ nó.
Những gì bạn có thể làm là nhập sprintf("%.20g")
số vào bộ đệm chuỗi sau đó thao tác để chuỗi chỉ có N ký tự vượt qua dấu thập phân.
Giả sử số của bạn nằm trong biến num, hàm sau sẽ xóa tất cả trừ các N
số thập phân đầu tiên , sau đó loại bỏ các số không ở cuối (và dấu thập phân nếu chúng đều là số không).
char str[50];
sprintf (str,"%.20g",num); // Make the number.
morphNumericString (str, 3);
: :
void morphNumericString (char *s, int n) {
char *p;
int count;
p = strchr (s,'.'); // Find decimal point, if any.
if (p != NULL) {
count = n; // Adjust for more or less decimals.
while (count >= 0) { // Maximum decimals allowed.
count--;
if (*p == '\0') // If there's less than desired.
break;
p++; // Next character.
}
*p-- = '\0'; // Truncate string.
while (*p == '0') // Remove trailing zeros.
*p-- = '\0';
if (*p == '.') { // If all decimals were zeros, remove ".".
*p = '\0';
}
}
}
Nếu bạn không hài lòng với khía cạnh cắt bớt (sẽ chuyển 0.12399
thành 0.123
thay vì làm tròn thành 0.124
), bạn thực sự có thể sử dụng các phương tiện làm tròn đã được cung cấp bởi printf
. Bạn chỉ cần phân tích số trước đó để tự động tạo độ rộng, sau đó sử dụng chúng để biến số thành chuỗi:
#include <stdio.h>
void nDecimals (char *s, double d, int n) {
int sz; double d2;
// Allow for negative.
d2 = (d >= 0) ? d : -d;
sz = (d >= 0) ? 0 : 1;
// Add one for each whole digit (0.xx special case).
if (d2 < 1) sz++;
while (d2 >= 1) { d2 /= 10.0; sz++; }
// Adjust for decimal point and fractionals.
sz += 1 + n;
// Create format string then use it.
sprintf (s, "%*.*f", sz, n, d);
}
int main (void) {
char str[50];
double num[] = { 40, 359.01335, -359.00999,
359.01, 3.01357, 0.111111111, 1.1223344 };
for (int i = 0; i < sizeof(num)/sizeof(*num); i++) {
nDecimals (str, num[i], 3);
printf ("%30.20f -> %s\n", num[i], str);
}
return 0;
}
Toàn bộ điểm nDecimals()
trong trường hợp này là tính toán chính xác độ rộng trường, sau đó định dạng số bằng cách sử dụng chuỗi định dạng dựa trên đó. Khai thác thử nghiệm main()
cho thấy điều này trong hoạt động:
40.00000000000000000000 -> 40.000
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.010
359.00999999999999090505 -> 359.010
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122
Khi bạn có giá trị được làm tròn chính xác, một lần nữa bạn có thể chuyển giá trị đó morphNumericString()
để loại bỏ các số không ở cuối bằng cách thay đổi:
nDecimals (str, num[i], 3);
thành:
nDecimals (str, num[i], 3);
morphNumericString (str, 3);
(hoặc gọi morphNumericString
ở cuối nDecimals
nhưng, trong trường hợp đó, tôi có thể chỉ kết hợp cả hai thành một hàm), và bạn kết thúc bằng:
40.00000000000000000000 -> 40
359.01335000000000263753 -> 359.013
-359.00999000000001615263 -> -359.01
359.00999999999999090505 -> 359.01
3.01357000000000008200 -> 3.014
0.11111111099999999852 -> 0.111
1.12233439999999995429 -> 1.122