关于浮点数(int)(float*10)遇到的问题

文章讨论了将float类型数据转换为整数时遇到的精度问题,解释了浮点数在计算机中的二进制表示并非精确,导致5.1*10转换后可能变为50而非预期的51,解决方案是四舍五入或加0.5后再转换。
摘要由CSDN通过智能技术生成

问题代码:

测试结果:

Time[i] =3.1  time=30

Time[i] =3.2  time=31

Time[i] =3.3  time=32

Time[i] =3.4  time=34

...

问题排查:(以下转自

MasterLuDa

最近遇到一个低级错误,哈哈,都不好意思讲出来,会犯这种低级错误。写此博客,记录我的低级错误,以防下次再犯。

问题是这样的,我有一些float类型的数据,我需要将这这些浮点型数据放大到整数,然后转换成int类型数据,比如float a=5.1 * 10就得到整数51,然后将浮点型数据51赋值给一个int型数据:int b=static_cast<int>(a),我满以为b的结果就是51,然而事实给了我一记耳光,结果居然是50!我觉得很奇怪,这明明没问题啊,不用电脑一眼就看出来就是51,怎么会变成50?当我将a=5.2*10转换成int时结果又变成51,而5.5*10转换成int时结果又是对的,即55,这就更奇怪了。

后来查阅float类型数据的表示方法,才恍然大悟,原来float类型数据在计算机中是不能用二进制精确表示的,计算机在计算浮点型数据的时候常常是不精确的。以上面的情况为例,浮点型数据5.1是由整数部分和小数部分组成,整数部分的二进制为101,二进制可以精确的表示;小数部分的表示如下:

0.1*2=0.2 取0
0.2*2=0.4 取0
0.4*2=0.8 取0
0.8*2=1.6 取1
0.6*2=1.2 取1
...
5.1=101.0001100110011001100110011...(计算过程可以查阅浮点数的二进制表示,https://www.cnblogs.com/hoip/articles/4555375.html)

可以看到小数部分是无限循环的,只有当小数部分为0.5是这个循环才结束,这就是为什么计算机无法精确表示浮点数的原因,也是为什么5.5*10转换成int没有出错的原因。将101.0001100110011001100110011小数点左移到第一个有效数字之后得到1.010001100110011001100110011...,从小数点后第一位开始数23位填充到float的尾数部分就得到float的尾数部分:01000110011001100110011,可见在这一步骤中又发生了一次不精确的取舍,小数点超出23位的部分舍去了,又损失了一次精度。上一步中移动了2位小数,因此指数部分为2+127=129,8位二进制为10000001,由于5.1是正数,因此符号位为0,所以5.1的二进制表示为:

0 10000001 01000110011001100110011

如果将上述二进制浮点数据转换成十进制,首先最高位为0,表示正数,取前8位:10000001=129,减去127为2,取前2位尾数部分01,首位添加1得到:101,即整数部分为101=5,23位尾数去掉已取走的2位得到小数部分:000110011001100110011=1/2*0+1/4*0+1/8*0+1/16*1+1/32*1+...=5.0999(保留4位小数),可见浮点数5.1在计算机中并不是存储的是5.1,而是一个无限接近5.1的数据,有可能是5.099999904...,也有可能是5.10002136...等。

至此提出的问题已经很清晰了,5.1*10的结果有可能是50.99999904,而在static_cast转int的时候,计算机是直接取整数部分,舍弃小数部分,因此结果就变成了50,而不是51。所以解决的方法就是四舍五入,或者是float数据加0.5再转换成int.即static_cast<int>(5.1*10+0.5)=51.
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/Mei20140912/article/details/110388788

解决:

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用[1]:在C语言中,指针是一种特殊的变量类型,它存储了一个变量的内存地址。指针变量可以指向不同类型的数据,包括整数、浮点数、字符等。指针变量的声明方式有多种形式,例如int *a和int* a都是合法的声明方式,它们都表示a是一个指向整数的指针变量。在声明多个指针变量时,需要注意每个指针变量的类型,例如int *a,b;只有a是指针变量,而int* a,b;则会让人误以为a和b都是指针变量[^1]。 引用:在C语言中,指针的使用非常灵活,可以通过指针来操作内存中的数据。int *p=0;表示将指针p初始化为0,即空指针。而int *p;*p=0;则表示先声明了一个指针变量p,然后将p指向的内存地址的值设置为0。需要注意的是,使用未初始化的指针可能会导致程序崩溃或产生不可预料的结果。另外,符号“&”用于获取变量的地址,例如&a表示变量a的地址[^2]。 根据提供的代码片段int ** dcmDimensionRnodeArray = new int * [nr]; void** ara = new void* [nr]; float** rna = new float * [nr];,可以看出这是在C++中动态分配了一个二维数组。其中,dcmDimensionRnodeArray是一个指向指针的指针变量,ara是一个指向void指针的指针变量,rna是一个指向浮点数指针的指针变量。这些指针变量分别指向了一个长度为nr的一维数组,每个元素都是一个指针。通过这种方式,可以实现多维数组的动态分配和访问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值