关于浮点数的精度丢失问题的思考

在实际编程中,我遇到了一些蛮有意思的情况,就是浮点型变量初始化是不精确的,但这个不精确数却是固定不变的?另外,为什么floatdouble的表示范围如此与众不同?

一 浮点数精度丢失的原因

浮点型表示单精度、双精度和扩展精度值。 C++ 标准指定了一个浮点数有效位数的最小值,然而大多数编译器都实现了更高的精度。 通常, float 以一个字(32比特)来表示,
double 以2个字(64比特)来表示,
long double 以3或4个字(96或128比特)来表示。
一般来说,类型 floatdouble 分别有7和16个有效位;类型 long double 则常常被用于有特殊浮点需求的硬件,它的具体实现不同,精度也各不相同。( 《C++ Primer第五版》 )

由以上描述,我们不难知道,对于 float 来说,最多只有7个有效位,这也就意味着,当实际存储的精度大于 float 的精度范围时,就会出现精度丢失现象。

二 精度丢失的深入提问

问题在于,所谓的有效位很让人迷惑,我明明占了那么多位置(float占4个字节double占8字节),为什么有效位只有6个?为什么整数位越多,精度越小?

三 浮点数精度问题的深入思考

1. 浮点数的表示

依据IEEE754二进制浮点数算术标准,一个浮点数可以表示为v = s * e * f(即符号位乘以指数偏移值再乘以分数值)

2. 计算机对浮点数的处理步骤

  1. 将浮点数转化成二进制
  2. 用二进制科学计数法表示
  3. 表示成IEEE 754格式
    其中在第一步和第三步中出现了精度丢失的情况

有了以上了解,我们就可以更好地理解浮点数的存储

3. 浮点数的存储

(1)存储步骤讲解

①第一步在这里插入图片描述
②第二步
在这里插入图片描述
③第三步
在这里插入图片描述
④一些特殊规定
在这里插入图片描述

(2)指数偏移量

表示单精度浮点数时,是用8位去存储指数部分,即表示0-255,但我们同样需要有负指数,正负指数的位数量为了均等,各自一半,-127-128。0是特殊点,特殊处理。储存时候会加上127,这样就刚刚好是0~255,就能很好的储存了,不然,不移量的话需要判断符号位来判断数值的正负。
在这里插入图片描述

(3)实际演示

在这里插入图片描述

四 float与double的范围和精度

范围

简称的类型名完整类型名长度(字节)取值范围
floatfloat4绝对值:3.4* 10-38~3.4* 1038
doubledouble8绝对值:1.7* 10-308~1.7* 10308
long doublelong double8绝对值:1.7* 10-308~1.7* 10308

float的指数位有8位,而double的指数位有11位,分布如下:
float
1bit(符号位) 8bits(指数位) 23bits(尾数位)
double
1bit(符号位) 11bits(指数位) 52bits(尾数位)
于是,float的指数范围为-127 ~ +128,而double的指数范围为-1023~+1024,并且指数位是按补码的形式来划分的。
float的范围为2^-128 ~ 2^128,也即3.40E-38 ~ +3.40E+38;double的范围为2^-1024 ~ +2^1024,也即1.79E-308 ~ +1.79E+308。

精度

float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。
float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字;
double:2^52 = 4503599627370496,一共16位,同理,double的精度为15~16位。

五 解决方法

通过网上查询资料,我得到一些方法:
double 类型可以解决大部分精度丢失问题(虽然它也会不精确,但日常精确度够用)
②C++中cout 其实是可以解决这种精度丢失问题的,但是影响效率(毕竟多读好多位)

#include<iostream>
using namespace std;

int main(void)
{
    float f_num1 = 21.75;
    float f_num2 = 13.45;
    cout << "f_num1 = " << f_num1 << endl;
    cout << "f_num2 = " << f_num2 << endl;
    cout << "f_num1 + f_num2 = " << f_num1 + f_num2 << endl;
    return 0;
}

浮点数转换成字符串类型,字符串存储时,不需要数据转换,也就不会出现精度丢失问题了。
④(不推荐,萌新发现,不知道坑在哪里)不在初始化的地方给值,偶现精度未丢失
这种方法肯定有问题,不然别人早发现了,另外在后期实验中,发现这种方法有时不起效果,仅仅作为一个小问题列出;

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值