关于c语言中%g(G)的用法和精度问题

格式说明符号g(G)在c标准中的说明是

g double Signed value printed in f or e format, whichever is more compact for the given value and precision. The e format is used only when the exponent of the value is less than –bai4 or greater than or equal to the precision argument. Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it.

翻译过来就是

1.把输出的值按照%e或者%f类型中输出长度较小的方式输出,仅当数值的指数小于-4或大于等于精度参数(默认值为6)时按%e(E)输出(否则按%f输出)。

2.(在选择好输出格式之后)尾部的零会被缩减。

3.(在选择好输出格式之后且0被缩减后)当小数点后面有一个或多个数字时才显示小数点。

下面是关于这些性质的演示

   printf("%g\n", 0.00001);

   printf("%f\n", 0.00001);

   printf("%e\n", 0.00001);

   printf("%g\n",1234567.0);
	
   printf("%g\n",123456.0);

输出结果:
1e-005
0.000010
1.000000e-005
1.23457e+006
123456

默认的精度为6所以%f与%e都显示了小数点后6位,这没问题。

指数小于-4所以%g转化将其成了指数输出,并且省略掉了本该输出在小数点后面的6个零,并在之后略掉了后面的小数点。如果减少一个0让指数变为-4,则%g将会以%f的形式输出并省略掉后面无效的0.

1234567的指数等于默认的精度6,故被按%e处理,而123456的指数5小于6故按%f处理。这里为什么变成了1.23457是因为
%g的精度既指明了使用%e所需要的指数大小,也指明了最大有效数字位数。

下面是默认精度下的截断演示

    printf("%g\n",0.0000123456789);
	
	printf("%e\n",0.0000123456789);

输出结果为
1.23457e-005
1.234568e-005

首先%e按照默认精度显示小数点后6位,这没问题。

对于%g,它按照默认的精度6从最大位开始截断,也就是1.23456。然后消0去小数点(当然这里没有)。这里的四舍五入是可能发生的,原理和用%.2f输出1.555结果是1.55而3.555结果是3.56一样,与浮点数的存储机制有关。

接下来我们尝试设定一个精度,同时混用%e,%f的精度以及宽长限制为防止读者混淆,看看输出情况。

   printf("%.3g\n", 110.1);
   
   printf("%010.2g\n", 110.1);

   printf("%010.2e\n", 110.1);

   printf("%.2e\n", 110.1);

   printf("%.2f\n", 110.1);

输出结果

110
001.1e+002
01.10e+002
1.10e+002
110.10

这里从下往上开始说明。

%.2f:指定小数点后精度为2,故加上一个0变成110.10。

%.2e:指点数值变为科学计数法后(即1.101x10的正2次方),然后取小数点后两位得1.10x10的正2次方。

%010.2e:这里用0修饰符以及10的字宽是为了提醒读者不要和数值截断混淆,因为即使这里的字宽超过了8也不会被截断。其他情况同上

%010.2g:010的解释和上面是一样的,都是把e与+算在字宽内。因为110.1的指数为2,>=指定精度2,故被转化成1.101x100。然后2作为截取精度从右往左截取(可能是四舍五入。要做到真正的四舍五入应该使用round函数或者a = int(a*100+0.5)/100.0之类的算法,这里不多做讨论)两位数变成了1.1,最终得到1.1e+002。

%.3g:这里因为指数2小于3,故被转化为%f,同时从右往左截取3位数输出,即110

最后是总结:对于一个使用%g转化说明的数值,不管其是指数小于-4或者大于等于精度参数(未指定的情况下默认为6)被转成了%e,还是不满足上述条件变成%f,都会先根据2,3进行简化。在简化后根据精度参数截取至最大有效数字位数(假如精度过大则不会补0使其强制变为精度确定的有效数字位数)。

%g运算符因为其能够自动简化输出中多余的0与小数点,常用于不指定输出格式的输出中

  • 30
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
以下是使用雅可比方法求矩阵A的全部特征值和特征向量的C语言代码: ``` #include <stdio.h> #include <math.h> #define N 3 //矩阵A的维数 int main() { double A[N][N] = {{2,-1,0},{-1,2,-1},{0,-1,2}}; //矩阵A double eps = 1e-8; //精度 double sum; //主对角线上元素的和 int i,j,k,p,q; //循环计数器 double max; //最大非主对角线元素的值 double c,s,t; //旋转角度sin、cos和tan double X[N][N]; //存放特征向量的矩阵 for(i = 0; i < N; i++) //初始化X为单位矩阵 for(j = 0; j < N; j++) X[i][j] = (i == j ? 1 : 0); while(1) { //求出矩阵A的主对角线元素之和 sum = 0; for(i = 0; i < N; i++) sum += A[i][i]; //如果最大非主对角线元素的绝对值小于精度,则停止迭代 max = 0; for(i = 0; i < N; i++) for(j = 0; j < N; j++) if(i != j && fabs(A[i][j]) > max) { max = fabs(A[i][j]); p = i; q = j; } if(max < eps) break; //计算旋转角度sin、cos和tan if(A[p][p] == A[q][q]) t = 1; else t = (2*A[p][q]) / (A[p][p] - A[q][q]); double sign = (t >= 0 ? 1 : -1); c = 1 / sqrt(1 + t*t); s = sign * t * c; //构造Givens矩阵 double G[N][N]; for(i = 0; i < N; i++) for(j = 0; j < N; j++) G[i][j] = (i == j ? 1 : 0); G[p][p] = c; G[p][q] = s; G[q][p] = -s; G[q][q] = c; //进行相似变换,更新矩阵A和特征向量矩阵X double temp[N][N]; for(i = 0; i < N; i++) for(j = 0; j < N; j++) temp[i][j] = 0; for(i = 0; i < N; i++) for(j = 0; j < N; j++) for(k = 0; k < N; k++) temp[i][j] += G[k][i] * A[k][j]; for(i = 0; i < N; i++) for(j = 0; j < N; j++) A[i][j] = 0; for(i = 0; i < N; i++) for(j = 0; j < N; j++) for(k = 0; k < N; k++) A[i][j] += temp[i][k] * G[k][j]; for(i = 0; i < N; i++) for(j = 0; j < N; j++) temp[i][j] = 0; for(i = 0; i < N; i++) for(j = 0; j < N; j++) for(k = 0; k < N; k++) temp[i][j] += G[k][i] * X[k][j]; for(i = 0; i < N; i++) for(j = 0; j < N; j++) X[i][j] = temp[i][j]; } //输出特征值和特征向量 printf("Eigenvalues:\n"); for(i = 0; i < N; i++) printf("%f\n", A[i][i]); printf("\nEigenvectors:\n"); for(i = 0; i < N; i++) { for(j = 0; j < N; j++) printf("%f ", X[j][i]); printf("\n"); } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值