免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9100 | 回复: 12
打印 上一主题 下一主题

[C] 关于c语言中的float和double运算误差问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2018-01-16 15:08 |只看该作者 |倒序浏览
操作系统:rhel7.0
gnu c lib: 2.17
项目是一个代理服务,将服务器的数据转发给客户,从客户获取数据转发给服务器, 除了glibc没有用到其它库
有这样一个问题:
服务器发送过来一个字符串“2277.24”, 代理将该串  atof(“2277.24”)  插入数据库,然后  atof(“2277.24”)*100  转发给客户端(代理运算时只处理整数,因此需要乘以100),客户端再除以100
问题来了, 数据库里是2277.24,客户端将该数字除以100后,得到的是2277.23

其实有一个很简单的方法测试该问题
printf(“%d\n”, (int)(2277.24*100)); //2277.24是double, 输出227723
printf(“%d\n”, (int)(2277.24f*100)); //2277.24f是float,输出227724

printf(“%d\n”, (int)(atof("2277.24")*100)); //atof("2277.24")返回的是double, 输出227723
printf(“%d\n”, (int)((float)atof("2277.24")*100)); //转换成float输出227724


我知道浮点数运算有误差,但最近项目里出现误差的客户端实在太多,我想用gmp或mpfr来解决精度问题, 但总感觉没有必要用一个庞大的库来解决这个问题

请高手指点





论坛徽章:
0
2 [报告]
发表于 2018-01-16 15:14 |只看该作者
*100 再/100小了。
你要的是两位小数,需要多留出一位进行四舍五入。所以应该*/1000。另外,c++ 有两个函数:ceil(),floor(),配合着用进行取整。

在一个项目中,我用了一个笨方法:先把float按位转成string,再根据最后一位数进行四舍五入。不想费脑子的话也可跟我学。

论坛徽章:
6
数据库技术版块每日发帖之星
日期:2015-11-27 06:20:00程序设计版块每日发帖之星
日期:2015-12-01 06:20:00每日论坛发贴之星
日期:2015-12-01 06:20:0015-16赛季CBA联赛之佛山
日期:2017-03-26 23:38:0315-16赛季CBA联赛之江苏
日期:2017-07-17 10:08:4415-16赛季CBA联赛之北京
日期:2018-03-04 17:01:50
3 [报告]
发表于 2018-01-16 15:26 |只看该作者
回复 2# sxcong

*/1000
这是一个好主意

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
4 [报告]
发表于 2018-01-16 15:58 |只看该作者
回复 1# faku

连printf的打印都知四舍五入...
你怎能...

  double a=2277.24;
  printf("%.2f\n", a*100);
  printf("%.12f\n",a*100);
  printf("%d  \n",(int)(a*100));
  printf("%d  \n",(int)(a*100+.5));

227724.00
227723.999999999971
227723  
227724  

论坛徽章:
0
5 [报告]
发表于 2018-01-16 16:04 |只看该作者
回复 4# jason680
内存数据不是想象的,比如1.5,很可能是1.499999999,这样,如果四舍五入保留整数,1.5应该是2,但这种情况下就是1,因为小数点后第一位是4。 浮点数在内存这个表现还是很头痛的。

论坛徽章:
3
巳蛇
日期:2013-10-03 10:41:48申猴
日期:2014-07-29 16:12:04天蝎座
日期:2014-08-21 09:24:52
6 [报告]
发表于 2018-01-16 16:05 |只看该作者
前段时间刚碰到
系统内部是double  1.23  ,对方需要 乘以10000 ,也就是 12300

int32(d_price*10000.0 + 0.5)

论坛徽章:
145
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07子鼠
日期:2013-11-18 18:48:57白羊座
日期:2013-11-29 10:09:11狮子座
日期:2013-12-12 09:57:42白羊座
日期:2013-12-24 16:24:46辰龙
日期:2014-01-08 15:26:12技术图书徽章
日期:2014-01-17 13:24:40巳蛇
日期:2014-02-18 14:32:59未羊
日期:2014-02-20 14:12:13白羊座
日期:2014-02-26 12:06:59
7 [报告]
发表于 2018-01-16 16:09 |只看该作者
回复 5# sxcong

what's your example ...

  double b=3/2.0;

  printf("%d  \n",(int)(b));
  printf("%d  \n",(int)(b+.5));

1  
2  


论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
8 [报告]
发表于 2018-01-16 16:36 |只看该作者
2277.24 实际值 2277.239999999999781721271574497222900390625
2277.24*100 实际值 227723.99999999997089616954326629638671875

2277.24f 实际值 2277.239990234375
2277.24f*100 实际值 227724.0

论坛徽章:
33
荣誉会员
日期:2011-11-23 16:44:17天秤座
日期:2014-08-26 16:18:20天秤座
日期:2014-08-29 10:12:18丑牛
日期:2014-08-29 16:06:45丑牛
日期:2014-09-03 10:28:58射手座
日期:2014-09-03 16:01:17寅虎
日期:2014-09-11 14:24:21天蝎座
日期:2014-09-17 08:33:55IT运维版块每日发帖之星
日期:2016-04-17 06:23:27操作系统版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-24 06:20:0015-16赛季CBA联赛之天津
日期:2016-05-06 12:46:59
9 [报告]
发表于 2018-01-17 12:19 |只看该作者
为啥数据库里要存小数?

如果是钱,直接 x 1000存成 分以下的整数就好了。

论坛徽章:
6
数据库技术版块每日发帖之星
日期:2015-11-27 06:20:00程序设计版块每日发帖之星
日期:2015-12-01 06:20:00每日论坛发贴之星
日期:2015-12-01 06:20:0015-16赛季CBA联赛之佛山
日期:2017-03-26 23:38:0315-16赛季CBA联赛之江苏
日期:2017-07-17 10:08:4415-16赛季CBA联赛之北京
日期:2018-03-04 17:01:50
10 [报告]
发表于 2018-01-17 19:45 |只看该作者
回复 9# q1208c

为啥数据库里要存小数?
大牛请教一个问题
数据库里为啥不能不存小数?
这是什么原因?
该怎么理解呢?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP