如何解决C语言浮点数精度丢失的问题?

测试网站:C语言在线运行,代码编译测试 - 在线编译器(nhooo.com)

1.循环加数据,误差越来越大:

float a = 99.2f;
	//float a = 1.3f;
	float b = 0;

for(int i =0; i<1000; i++){
		b = b + a;
	}

for(int i =0; i<10000; i++){
		b = b + a;
	}

printf("%fn", a);
	printf("---%fn", b);

输出:

99.199997
---99200.695312
---991913.875000

1000次的时候还好。

10000次的时候,误差已经到了100。

解决方法:1.转化成整数再运算;在进行大量的浮点数运算时,为了提高运算的速度和准确性,可以考虑将小数转换为整数进行计算,再将结果转换回小数。

2.看看开源代码中C语言的算法是怎么算的;

3.都转成double,这样10000次计算结果是---991999.969482。尽量避免使用float类型。虽然float类型能够节省内存空间,但是其精度不够高,容易导致精度丢失。在精度要求比较高或需要进行复杂计算时,建议使用double类型。

2.比较两个数的大小,必须用一个float.h的宏定义EPS最小误差来定。大概0.000001.精确到6位。

double test=0.1;
    if(fabs(test-(1-0.9))<0.0001)
    {
        printf("正常");
    }
    else
    {
        printf("what!!!");
    }

3.C语言发送双精度到Java语言,需要精确到前两位发送。具体思路是转换成字符。

float ddd = (float)( (a+0.001)*100) / 100;
	printf("四舍五入%fn", ddd);

float ff=1024.58;
  double dd=12345678901234.58;
  char strff[21],strdd[21];
	sprintf(strff,"%.2f",ddd);
	printf("strff=%sn",strff);  // 输出strff=1024.58
	float e = atof(strff);
	printf("%fn", e);

输出

四舍五入99.200996

strff=99.20
99.199997  二进制就是这样,想只显示两位是不可能的!

Java端再调用BigDecimal类型进行计算。在进行精度要求极高的计算时,可以使用Java提供的BigDecimal类型进行计算,它能够保证精度不会损失。不过注意:BigDecimal类型的计算效率较低

1. 由于计算机中浮点数表示的方式为近似值,所以在进行浮点数的比较时,需要使用特定的比较方式,避免误判。例如:Math.abs(a - b) < 0.000001,表示a和b的差值小于0.000001。

2. 在进行除法运算时,需要判断被除数是否为0,避免抛出异常。

3. 浮点数中可能出现的NaN(Not a Number)或Infinity值需要进行特殊处理,否则可能导致程序异常终止。

4.C、Java默认的是double类型,用小数最好不要用 .f ,否则会出现误差

C语言调用 Math.round 将小数四舍五入到整数

float a = 99.4999;
    a = round(a);

printf("%fn", a);

5. Java 发送小数到C

//String value of 会丢失精度
NumberFormat nf = NumberFormat.getInstance();
nf.setGroupingUsed(false);
String s1 = nf.format(value);

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>