Say I have a couple of values with uncertainty estimates
double x, sigma_x;
e.g.
45.34302958634 ± 4.25976343
3.52986798343 ± 0.2363467
3.3734874533e+12 ± 6.34659e+6
Clearly, most of those decimals aren't significant. How do I choose the correct number of “significant digits” (what does that even mean?), to always get as many decimals as needed out of printf
, but no more?
I.e. I want some definition of char* fmtString
, dependent on sigma_x
, such that
printf(fmString, x)
yields
45
3.5
3.373487e+12
答案 0 :(得分:1)
以下代码为测试数据输出以下内容:
45
3.5
3.373487e+12
这完全符合要求,而且不会受到我原始解决方案中的缺陷的影响,而且更简单。
floor( log10(sigma) )
确定与小数点相关的最后一位有效数字的位置。表达式的其余部分基本上将非有效数字归零。如此调整的值,可以根据需要使用受支持的浮点格式说明符进行打印。
#include <stdio.h>
#include <math.h>
double fn( double x, double sigma )
{
return x - fmod( x, pow( 10, floor( log10(sigma) ) ) );
}
int main()
{
struct
{
double x ;
double sigma ;
} data[] = {{45.34302958634, 4.25976343},
{3.52986798343, 0.2363467},
{3.3734874533e+12, 6.34659e+6}} ;
for( int i = 0; i < sizeof(data)/sizeof(*data); i++ )
{
double xs = fn( data[i].x, data[i].sigma ) ;
printf( "%.7g\n", xs ) ;
}
return 0 ;
}
答案 1 :(得分:1)
关于如何格式化输出,我不清楚这个问题。但是当我明白了,
printf("%.*g", precision, number);
似乎还不错。
那么,如何计算精度?
这肯定不是最快的方式。但你可以像在纸上那样做。
int calc_width(double n, double d)
{
char s[300], e[300]; //300?? I don't know how much to use. ;)
int i, j = 0;
//write them down
sprintf(s, "%f", n-d/100);
sprintf(e, "%f", n+d/100);
//see how many are same
for(i=0; s[i] == e[i]; i++)
if(s[i] == '.') j = 1; //well, see 'man printf'
return i-j;
}
测试:
int main()
{
double n[] = {45.34302958634, 3.52986798343, 3.3734874533e+12};
double d[] = {4.25976343, 0.2363467, 6.34659e+6};
int i;
for(i=0; i<3; i++)
printf("%.*g\n", calc_width(n[i], d[i]), n[i]);
return 0;
}
结果:
45.3
3.5
3.373487e+12
答案 2 :(得分:0)
Use this:
printf("%.*g", precision, number);
with precision
computed from your sigma_x
as you desire.
答案 3 :(得分:0)
使用"%.*e"
控制小数点后的位数。
包括各种测试以确保理智的精确度。
不同意45.34302958634 ± 4.25976343
应打印为45
,而不是45.3
- 但这是一个数学细节。根据需要调整精度计算。
OP不清楚何时使用指数表示法。 "%.*g"
如果符合OP的未说明的截止,则会在那里获得代码。
#include <float.h>
#include <math.h>
// #define DBL_DECIMAL_DIG (DBL_DIG + 3)
void print_number_sigma(double x, double sigma_x) {
double precision = sigma_x*x ?
ceil(log10(fabs(x)) - log10(fabs(sigma_x))) :
DBL_DECIMAL_DIG - 1;
if (precision <= 0) precision = 1;
else if (precision >= DBL_DECIMAL_DIG) precision = DBL_DECIMAL_DIG - 1;
printf("%.*e +/- %e\n", (int) precision, x, sigma_x);
}
int main(void) {
print_number_sigma(45.34302958634, 4.25976343);
print_number_sigma(3.52986798343, 0.2363467);
print_number_sigma(3.3734874533e+12, 6.34659e+6);
return 0;
}
输出
4.53e+01 +/- 4.259763e+00
3.53e+00 +/- 2.363467e-01
3.373487e+12 +/- 6.346590e+06