C语言计算小数精度问题

zhendeguofenle 2020-05-19 04:11:34
如题,在进行C语言编程时,在一个循环计算中b值我用手算是0.00003648249,而c语言计算值是0.00003650136900,虽然看起来很小,但在后续计算中影响很大,如何保证该数的计算精度,相关代码如下,运行环境是vs上的原始c

double Cpd, dend,kd,r,nr,b
Cpd = 750.0;
dend = 3900.0;
kd = 8.70;
r = 0.0011
nr = 0.00001
b = Cpd *dend *(r *r *r - (r - nr)*(r - nr)*(r - nr)) / 3.0 + kd *nt *(r *r + (r0 - nr)*(r0 - nr)) / nr;
printf("\n%16.15lf\n",a);
...全文
726 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
nice_cxf 2020-05-25
  • 打赏
  • 举报
回复
引用 6 楼 zhendeguofenle 的回复:
[quote=引用 5 楼 nice_cxf 的回复:] 大小差距接近千分之三,肯定不是精度问题,核对下是不是那里计算有错误? double运算精度不可能差这么多
计算没问题,只有这一个数差这么多,其他的都很准,至少有十一位精度[/quote] 感觉不太可能,你可以加一些临时变量一步一步核对下看看哪里的问题,浮点计算应该不会有这种问题,double才3个有效位,不太应该
zhendeguofenle 2020-05-20
  • 打赏
  • 举报
回复
引用 1 楼 自信男孩 的回复:
后面的计算中,是否可以考虑省略获取b的过程,比如1/3.0不用0.33333而用1/3.0呢?
本来是没有b这个参数的,是我排错的时候自己加的输出,这个b是个除数,至于你说的不用0.3333而用1/3.0,我不就是这么用的吗,没用0.3333啊,我不是这个专业的,只是本科学过c语言,加上自学一点,可能有些基础知识不清楚,希望你能说清楚一点
zhendeguofenle 2020-05-20
  • 打赏
  • 举报
回复
引用 5 楼 nice_cxf 的回复:
大小差距接近千分之三,肯定不是精度问题,核对下是不是那里计算有错误? double运算精度不可能差这么多
计算没问题,只有这一个数差这么多,其他的都很准,至少有十一位精度
nice_cxf 2020-05-20
  • 打赏
  • 举报
回复
大小差距接近千分之三,肯定不是精度问题,核对下是不是那里计算有错误? double运算精度不可能差这么多
zhendeguofenle 2020-05-20
  • 打赏
  • 举报
回复
引用 3 楼 qybao 的回复:
[quote=引用 2 楼 zhendeguofenle 的回复:] 本来是没有b这个参数的,是我排错的时候自己加的输出,这个b是个除数,至于你说的不用0.3333而用1/3.0,我不就是这么用的吗,没用0.3333啊,我不是这个专业的,只是本科学过c语言,加上自学一点,可能有些基础知识不清楚,希望你能说清楚一点
1L的意思可能是说通分 即 b = Cpd *dend *(r *r *r - (r - nr)*(r - nr)*(r - nr)) / 3.0 + kd *nt *(r *r + (r0 - nr)*(r0 - nr)) / nr; 等价于 b = (Cpd *dend *(r *r *r - (r - nr)*(r - nr)*(r - nr)) ) + 300000*(kd *nt *(r *r + (r0 - nr)*(r0 - nr)))) / 3.0; 也就是nr也变成分母为3.0,先计算总和最后再除以3.0 计算过程中减少精度丢失,或许一定程度上能保证一定的精度吧 我觉得你可以考虑一下第三方提供的高精度类型或自己实现一个高精度类型 如GCC Quad-PrecisionMath Library(简称为quadmath)提供的__float128 或者boost lib的cpp_dec_float 自己实现的话,可以参考 https://blog.csdn.net/housisong/article/details/525215 [/quote]好的,通分的意义是在于将小数变大先进行计算再变小对吧,至于高精度类型我去看看,谢了
qybao 2020-05-20
  • 打赏
  • 举报
回复
引用 2 楼 zhendeguofenle 的回复:
本来是没有b这个参数的,是我排错的时候自己加的输出,这个b是个除数,至于你说的不用0.3333而用1/3.0,我不就是这么用的吗,没用0.3333啊,我不是这个专业的,只是本科学过c语言,加上自学一点,可能有些基础知识不清楚,希望你能说清楚一点

1L的意思可能是说通分

b = Cpd *dend *(r *r *r - (r - nr)*(r - nr)*(r - nr)) / 3.0 + kd *nt *(r *r + (r0 - nr)*(r0 - nr)) / nr;
等价于
b = (Cpd *dend *(r *r *r - (r - nr)*(r - nr)*(r - nr)) ) + 300000*(kd *nt *(r *r + (r0 - nr)*(r0 - nr)))) / 3.0;
也就是nr也变成分母为3.0,先计算总和最后再除以3.0
计算过程中减少精度丢失,或许一定程度上能保证一定的精度吧
我觉得你可以考虑一下第三方提供的高精度类型或自己实现一个高精度类型
如GCC Quad-PrecisionMath Library(简称为quadmath)提供的__float128
或者boost lib的cpp_dec_float
自己实现的话,可以参考
https://blog.csdn.net/housisong/article/details/525215


自信男孩 2020-05-19
  • 打赏
  • 举报
回复
后面的计算中,是否可以考虑省略获取b的过程,比如1/3.0不用0.33333而用1/3.0呢?

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧