printf double 在可用宽度中具有最大精度
printf double with maximum precision in available width
我需要在 C 中打印双精度,宽度为 20,但使用 20 个字符中可以打印的最大精度
例如:
-123.123456789123456789
应该打印:
-123.1234567891234568
到目前为止,我有以下代码可以工作,但是很丑并且有问题:
double num = .......;
int pr = 0;
char temp[32] = { 0 };
char *point = NULL;
sprintf(temp, "%.20f", num);
point = strchr(temp, '.');
if (point) {
pr = 20 - (1 + point - temp);
}
printf("%20.*f", pr, num);
问题是这不适用于 %g 而不是 %f,它有时会打印超过 20 个字符,即使不存在指数部分。
当给出像 0.000123456789123456789 这样的数字时,就会出现问题。小数点后多出来的零好像不算(!).
根据 chux and this answer 的一些提示,我实施了以下似乎有效的解决方案。
我不再尝试预先计算要使用的正确精度,而是以足够的精度打印,然后我裁剪掉多余的数字。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void printDouble(double val, int width)
{
char *temp = malloc((width + 32) * sizeof(char));
int len = 0;
sprintf(temp, "%*.*g", width, width, val);
len =strlen(temp);
if (len > width) {
char *dropped = temp + width;
char *last = dropped - 1;
char *expon = strchr(temp, 'E');
if (!expon)
expon = strchr(temp, 'e');
if (expon) {
last = temp + width - 1 - strlen(expon);
dropped = last + 1 < expon ? last + 1 : NULL;
}
if (strchr(temp, '.')) {
/* Round */
if (dropped && *dropped >= '5' && *dropped <= '9') {
while (*last == '9')
last--;
(*last)++;
}
/* Remove trailing zeroes */
while (*last == '0')
last--;
}
if (expon) {
while (*expon != '[=10=]')
*(++last) = *(expon++);
}
*(++last) = '[=10=]';
}
printf("%*s\n", width, temp);
free(temp);
}
我需要在 C 中打印双精度,宽度为 20,但使用 20 个字符中可以打印的最大精度
例如:
-123.123456789123456789
应该打印:
-123.1234567891234568
到目前为止,我有以下代码可以工作,但是很丑并且有问题:
double num = .......;
int pr = 0;
char temp[32] = { 0 };
char *point = NULL;
sprintf(temp, "%.20f", num);
point = strchr(temp, '.');
if (point) {
pr = 20 - (1 + point - temp);
}
printf("%20.*f", pr, num);
问题是这不适用于 %g 而不是 %f,它有时会打印超过 20 个字符,即使不存在指数部分。 当给出像 0.000123456789123456789 这样的数字时,就会出现问题。小数点后多出来的零好像不算(!).
根据 chux and this answer 的一些提示,我实施了以下似乎有效的解决方案。 我不再尝试预先计算要使用的正确精度,而是以足够的精度打印,然后我裁剪掉多余的数字。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void printDouble(double val, int width)
{
char *temp = malloc((width + 32) * sizeof(char));
int len = 0;
sprintf(temp, "%*.*g", width, width, val);
len =strlen(temp);
if (len > width) {
char *dropped = temp + width;
char *last = dropped - 1;
char *expon = strchr(temp, 'E');
if (!expon)
expon = strchr(temp, 'e');
if (expon) {
last = temp + width - 1 - strlen(expon);
dropped = last + 1 < expon ? last + 1 : NULL;
}
if (strchr(temp, '.')) {
/* Round */
if (dropped && *dropped >= '5' && *dropped <= '9') {
while (*last == '9')
last--;
(*last)++;
}
/* Remove trailing zeroes */
while (*last == '0')
last--;
}
if (expon) {
while (*expon != '[=10=]')
*(++last) = *(expon++);
}
*(++last) = '[=10=]';
}
printf("%*s\n", width, temp);
free(temp);
}