首页 > 其他分享 >float小,double大,我把小的数放到大的空间里面,为什么还会有精度损失?

float小,double大,我把小的数放到大的空间里面,为什么还会有精度损失?

时间:2024-10-06 20:19:14浏览次数:8  
标签:二进制 double float 近似值 2.3 精度

让我们来看这样一个例子:

double a = 2.3F;
System.out.println(a);

输出的 a 为 2.299999952316284

不再是 2.3 了!

明明 float 小,double 大,我把小的数放到大的空间里面,为什么还会有“精度损失”?

关键点是表示精度而非“空间”大小:

  1. 浮点数的存储机制(IEEE 754 标准):

    • floatdouble 都是基于 IEEE 754 标准存储浮点数。它无法精确存储所有的十进制小数,原因在于 二进制表示系统的局限性
    • float 使用 32 位,其中 1 位用于符号,8 位用于指数,23 位用于尾数(也叫有效位数)。
    • double 使用 64 位,其中 1 位用于符号,11 位用于指数,52 位用于尾数。

    因此,float 的尾数只能存储 23 位有效数字,而 double 的尾数可以存储 52 位有效数字。

  2. 浮点数在二进制中的表示限制:
    浮点数通常不能被精确表示为二进制数。例如,2.3 是一个十进制数,但在二进制中它无法被精确表示,只能是一个近似值。

    • 当你在 Java 中声明 float a = 2.3F; 时,Java 会将 2.3 转换成其在 float 类型中的二进制近似值,这个近似值是 2.2999999523162841796875(其二进制表示)。
    • 由于 float 的精度只有 23 位尾数,所以它只能表示到这么精确的值,即我们看到的四舍五入结果为 2.3
  3. floatdouble 的转换:
    当你将 float 转换为 double 时,不会发生“精度损失”,只是 double 能够表示得更加精确,它可以保留 float 的原始二进制表示,但仍然是 float 精度的近似值(这是因为它来自 float 的有限精度的二进制近似)。

    • float 的精度是 23 位尾数,即它的二进制近似值是 2.2999999523162841796875
    • 当这个值转换为 double 时,double 可以表示更多的位数(52 位尾数),于是它就显示出了更多原始 float 的二进制近似值的真实数字,即 2.299999952316284
  4. 为什么看起来像是“损失精度”?
    并不是你在 double 中“损失了精度”,而是由于 float 本身的精度有限,它只能表示出一个有限的近似值。这个近似值在被转换为 double 时,double 可以显示更多的二进制位数,于是你看到的是 float 原本就不够精确的数字。

    换句话说,float 被转化为 double 时,并没有损失任何精度,只是 double 展现了 float 精度限制下的原本“隐藏的”部分

总结:

  • float a = 2.3F;:由于 float 的精度限制,它存储的近似值是 2.2999999523162841796875,但显示为 2.3
  • double a = 2.3F;:当 float 的二进制近似值被存储到 double 时,double 能显示出更多的尾数位数,展示了原本 float 类型未能显示的那部分,即 2.299999952316284

补充具体说明:

计算机在底层使用二进制存储数值,但并非所有的十进制小数都可以用二进制精确表示。这与我们用十进制表示某些分数(如 1/3)时需要无限循环小数类似。

float 在 Java 中是一个 32 位的浮点类型,它能够精确存储的数的范围主要是有限的离散值

在十进制系统中,数字 2.3 的分数表示是 23/10。当我们将这个十进制数转换为二进制时,它无法表示为一个精确的有限二进制小数,因为:

  • 二进制中只能精确表示某些分数,比如 1/2, 1/4, 1/8 等,都是 2 的幂。
  • 2.3 并不是可以通过这些简单的 2 的幂表示出来的,因此它只能近似表示为一个有限的二进制数。

具体来说,2.3 转换为二进制后的无限小数大致是:

2.3 ≈ 10.0100110011001100110011...(无限循环)

由于计算机的位数有限,它无法存储无限位数的小数,因此只能截断,导致了精度误差。

对于像 1.2345678 这样的数字,float 可以精确表示。

但是对于像 2.3 这样的数字,它不能被精确表示,因为它无法在有限的位数内表示该小数的二进制表示。

如果需要表示精度更高的数字,应该使用 double 类型,它使用 64 位存储浮点数,拥有更大的尾数位数(52 位),可以表示大约 15 位十进制有效数字

但是,即便使用 double,并不是所有的十进制数仍然都可以精确表示,因为这是二进制系统的固有限制。

如果需要更高的精度,应考虑使用 doubleBigDecimal 来表示和计算精确的十进制值。

标签:二进制,double,float,近似值,2.3,精度
From: https://blog.csdn.net/2404_87410060/article/details/142716932

相关文章

  • java中,8个字节的long为什么可以自动转换为4个字节的float
    在Java中,long类型是8个字节(64位)的整数,而float类型是4个字节(32位)的单精度浮点数。虽然long有更大的字节数,但它可以自动转换为float。这是因为两者的表示形式和数据范围不同。1.表示方式的差异long类型:long是64位有符号整数,表示的数值范围是-2^63到2^......
  • 高精度加法笔记
    vector<int>u;//储存a倒序的每个数vector<int>v;//储存b倒序的每个数vector<int>add(vector<int>m,vector<int>n){//高精度加法 vector<int>temp;//temp数组存储相加后的每个数 intt=0;//t作为每个数相加的和 for(inti=0;i<m.size()||i<n.size();......
  • 高精度算法-减法
    ​//高精度算法-减法#include<iostream>#include<string>#include<vector>#include<cmath>usingnamespacestd;intmain(){strings1,s2;//减法.getline(cin,s1);getline(cin,s2);//减法的2个必要数字.inta1[200]={0};inta2[200......
  • 高精度(1)——高精度减法
    题目描述给定两个正整数(不含前导0),计算它们的差,计算结果可能为负数。输入格式共两行,每行包含一个整数。输出格式共一行,包含所求的差。数据范围1≤整数长度≤100000输入样例3211输出样例21注释版代码#include<iostream>#include<vector>usingnamespacestd;//......
  • vue中使用decimal.js对前端数值类型进行高精度计算
    需求背景:由于一些场景我们需要在前端JavaScript进行数值计算,且对精度要求比较严谨,而前端数值是浮点类型,直接使用计算可能会产生一系列的精度问题,常见的浮点运算问题,比如精度损失等;所以例如涉及到一些金额计算等,需要进行高精度处理。解决方案:(1)可以把数值计算部分逻辑交给后端接口......
  • YOLOv8改进 - 注意力篇 - 引入(A2-Nets)Double Attention Networks注意力机制
    一、本文介绍作为入门性篇章,这里介绍了A2-Nets网络注意力在YOLOv8中的使用。包含A2-Nets原理分析,A2-Nets的代码、A2-Nets的使用方法、以及添加以后的yaml文件及运行记录。二、A2-Nets原理分析A2-Nets官方论文地址:A2-Nets文章A2-Nets注意力机制(双重注意力机制):它从输入图......
  • 要求实现一个函数 DoubleToStr(double a,int b,char * str),将参数 a 转化为字符串 str
    sprintf函数:sprintf(str,"%.*f",b,a);:sprintf是一个格式化输出函数,类似于printf,但它将输出写入到字符串中而不是标准输出。"%.*f":#include<stdio.h>//将双精度浮点数a转换为字符串str,小数点后保留b位voidDoubleToStr(doublea,intb,char*str){  //......
  • 枚举,精度,四则运算,加合集
    一.枚举类型仔细阅读示例:EnumTest.java,运行它,分析运行结果?代码如下:`publicclassEnumTest{publicstaticvoidmain(String[]args){ Sizes=Size.SMALL; Sizet=Size.LARGE; //s和t引用同一个对象? System.out.println(s==t); //是原始数据类型吗? System.out.pri......
  • Java中浮点数运算存在的精度问题以及解决方法
    观察以下一段代码,相信小朋友都可以一眼看出答案,但是计算机给出的答案是这样吗?publicclassTestDouble{publicstaticvoidmain(Stringargs[]){System.out.println("0.05+0.01="+(0.05+0.01));System.out.println("1.0-0.42="+(1.0-0.42));System.out.pr......
  • 高精度人员定位系统在化工企业中的应用-天拓四方
    在化工行业中,安全管理是企业运营不可忽视的重要环节。由于化工企业工作环境复杂多变,存在诸多潜在的安全隐患,如易燃易爆气体、有毒化学物质等,因此,保障员工的安全显得尤为重要。高精度人员定位系统在化工企业的应用实时定位与监控在化工企业中,员工经常需要在复杂的环境中进行作业,如进......