忘记密码   免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 徽章 文库 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
12下一页
最近访问板块 发新帖
查看: 2619 | 回复: 12

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

论坛徽章:
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
发表于 2018-01-16 15:14 |显示全部楼层
*100 再/100小了。
你要的是两位小数,需要多留出一位进行四舍五入。所以应该*/1000。另外,c++ 有两个函数:ceil(),floor(),配合着用进行取整。

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

论坛徽章:
5
数据库技术版块每日发帖之星
日期: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:44
发表于 2018-01-16 15:26 |显示全部楼层
回复 2# sxcong

*/1000
这是一个好主意

论坛徽章:
128
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07巳蛇
日期:2014-05-09 16:43:18巨蟹座
日期:2014-10-23 17:48:38子鼠
日期: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
发表于 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
发表于 2018-01-16 16:04 |显示全部楼层
回复 4# jason680
内存数据不是想象的,比如1.5,很可能是1.499999999,这样,如果四舍五入保留整数,1.5应该是2,但这种情况下就是1,因为小数点后第一位是4。 浮点数在内存这个表现还是很头痛的。

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

int32(d_price*10000.0 + 0.5)

论坛徽章:
128
技术图书徽章
日期:2013-10-01 15:32:13戌狗
日期:2013-10-25 13:31:35金牛座
日期:2013-11-04 16:22:07巳蛇
日期:2014-05-09 16:43:18巨蟹座
日期:2014-10-23 17:48:38子鼠
日期: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
发表于 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
发表于 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-09-03 16:01:17天蝎座
日期:2014-08-21 17:18:48丑牛
日期:2014-08-29 16:06:45天秤座
日期:2014-08-29 10:12:18天秤座
日期:2014-08-26 16:18:20双子座
日期:2014-07-30 11:38:27寅虎
日期:2014-08-04 10:24:12IT运维版块每日发帖之星
日期: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
发表于 2018-01-17 12:19 |显示全部楼层
为啥数据库里要存小数?

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

论坛徽章:
5
数据库技术版块每日发帖之星
日期: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:44
发表于 2018-01-17 19:45 |显示全部楼层
回复 9# q1208c

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

本版积分规则

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP