精华内容
下载资源
问答
  • 之所以再次提起32位浮点数,是因为在今天交接工作过程中想到一年前在调试双口RAM过程中遇到的一个问题,当年在兴奋的解决掉这个问题之后,又迫不及待的赶进度,以至于当时的调试笔记没有做好,现在想到这个问题还要...
  • IEEE754标准

    2018-06-04 15:29:22
    希望有所帮助 ,
  • IEEE 754标准

    2021-01-17 16:28:32
    为此,美国IEEE(电器及电子工程师协会)提出了一个从系统角度支持浮点数的表示方法,称为IEEE754标准(IEEE,1985),当今流行的计算机几乎都采用了这一标准。Java中浮点数,既float和double,都是采用的IEEE754标准。...

    由于不同机器所选用的基数、尾数位长度和阶码位长度不同,因此对浮点数的表示有较大差别,这不利于软件在不同计算机之间的移植。为此,美国IEEE(电器及电子工程师协会)提出了一个从系统角度支持浮点数的表示方法,称为IEEE754标准(IEEE,1985),当今流行的计算机几乎都采用了这一标准。

    Java中浮点数,既float和double,都是采用的IEEE754标准。无论在java python javaScript里面都存在 1 + 2 != 3 问题,这个问题的产生根源在于计算存储数字是二进制,对无限循环小数和无理数采用双精度64位double浮点数_float为32位,即52位小数+11位指数+1位符号。超过52位小数溢出而产生精度丢失。

    例如在 chrome js console 中:

    // 加法

    0.1 + 0.2 = 0.30000000000000004

    0.1 + 0.7 = 0.7999999999999999

    0.2 + 0.4 = 0.6000000000000001

    // 减法

    0.3 - 0.2 = 0.09999999999999998

    1.5 - 1.2 = 0.30000000000000004

    // 乘法

    0.8 * 3 = 2.4000000000000004

    19.9 * 100 = 1989.9999999999998

    // 除法

    0.3 / 0.1 = 2.9999999999999996

    0.69 / 10 = 0.06899999999999999

    // 比较

    0.1 + 0.2 === 0.3 // false

    (0.3 - 0.2) === (0.2 - 0.1) // false

    这个问题并不只是在Javascript中才会出现,任何使用二进制浮点数的编程语言都会有这个问题,只不过在 C++/C#/Java 这些语言中已经封装好了方法来避免精度的问题,而 JavaScript 是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。

    7c636d8f18d5

    7c636d8f18d5

    浮点数丢失产生原因

    JavaScript 中的数字类型只有 Number 一种,Number 类型采用 IEEE754 标准中的 “双精度浮点数” 来表示一个数字,不区分整数和浮点数。

    什么是IEEE-745浮点数表示法

    IEEE-745浮点数表示法是一种可以精确地表示分数的二进制示法,比如1/2,1/8,1/1024

    十进制小数如何表示为转为二进制

    十进制整数转二进制

    十进制整数换成二进制一般都会:1=>1 2=>10 3=>101 4=>100 5=>101 6=>110

    6/2=3…0

    3/2=1…1

    1/2=0…1

    倒过来就是110

    十进制小数转二进制

    0.25的二进制

    0.25*2=0.5 取整是0

    0.5*2=1.0    取整是1

    即0.25的二进制为 0.01 ( 第一次所得到为最高位,最后一次得到为最低位)

    0.8125的二进制

    0.8125*2=1.625   取整是1

    0.625*2=1.25     取整是1

    0.25*2=0.5       取整是0

    0.5*2=1.0        取整是1

    即0.8125的二进制是0.1101(第一次所得到为最高位,最后一次得到为最低位)

    0.1的二进制

    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

    0.2*2=0.4======取出整数部分0

    0.4*2=0.8======取出整数部分0

    0.8*2=1.6======取出整数部分1

    0.6*2=1.2======取出整数部分1

    接下来会无限循环

    0.2*2=0.4======取出整数部分0

    0.4*2=0.8======取出整数部分0

    0.8*2=1.6======取出整数部分1

    0.6*2=1.2======取出整数部分1

    所以0.1转化成二进制是:0.0001 1001 1001 1001…(无限循环)

    0.1 => 0.0001 1001 1001 1001…(无限循环)

    同理0.2的二进制是0.0011 0011 0011 0011…(无限循环)

    科普科学计数法

    科学记数法是一种把一个数表示成a与10的n次幂相乘的形式(1≤a<10,n为整数)的记数法。

    例如:19971400000000=1.99714×10^13。计算器或电脑表达10的幂是一般是用E或e,也就是1.99714E13=19971400000000。

    科学记数法的形式是由两个数的乘积组成的。表示为a×10^b(aEb),其中一个因数为a(1≤|a|<10),另一个因数为10^n。

    科学计数法的精确度

    运用科学记数法a×10^n的数字,它的精确度以a的最后一个数在原数中的数位为准。

    13600,精确到十位,记作:1.360X10^4

    13600 ,精确到百位,记作:1.36X10^4

    13600,精确到千位,记作:1.3X10^4

    十进制的5.0,写成二进制是101.0,相当于1.01×2^2

    十进制的-5.0,写成二进制是-101.0,相当于-1.01×2^2,推荐阅读《浮点数的二进制表示》

    在二进制里面,即a×2^b,1≤a<2,也就是说,a可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。IEEE 754规定,在计算机内部保存a时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以64位浮点数为例,留给a只有52位,将第一位的1舍去以后,等于可以保存53位有效数字

    所以js浮点数表示的数字为[-1*2^53*2^1023,1*2^53*2^1024] ,±1 为符号位,2^53 为小数位(53-1), 2^1024 1024位指数位(1024*2=2048=2^11为指数位)

    IEEE-745浮点数表示法存储结构

    在 IEEE754 中,双精度浮点数采用 64 位存储,即 8 个字节表示一个浮点数 。其存储结构如下图所示:

    7c636d8f18d5

    指数位可以通过下面的方法转换为使用的指数值:

    7c636d8f18d5

    IEEE-745浮点数表示法记录数值范围

    从存储结构中可以看出, 指数部分的长度是11个二进制,即指数部分能表示的最大值是 2047(2^11-1)

    取中间值进行偏移,用来表示负指数,也就是说指数的范围是 [-1023,1024]

    因此,这种存储结构能够表示的数值范围为 2^1024 到 2^-1023 ,超出这个范围的数无法表示 。2^1024  和 2^-1023  转换为科学计数法如下所示:

    1.7976931348623157 × 10^308

    5 × 10^-324

    因此,JavaScript 中能表示的最大值是 1.7976931348623157 × 10^308,最小值为 5 × 10-324 。java双精度类型 double也是如此。

    这两个边界值可以分别通过访问 Number 对象的 MAX_VALUE 属性和 MIN_VALUE 属性来获取:

    Number.MAX_VALUE; // 1.7976931348623157e+308

    Number.MIN_VALUE; // 5e-324

    如果数字超过最大值或最小值,JavaScript 将返回一个不正确的值,这称为 “正向溢出(overflow)” 或 “负向溢出(underflow)” 。

    Number.MAX_VALUE+1 == Number.MAX_VALUE; //true

    Number.MAX_VALUE+1e292; //Infinity

    Number.MIN_VALUE + 1; //1

    Number.MIN_VALUE - 3e-324; //0

    Number.MIN_VALUE - 2e-324; //5e-324

    IEEE-745浮点数表示法数值精度

    在 64 位的二进制中,符号位决定了一个数的正负,指数部分决定了数值的大小,小数部分决定了数值的精度。

    IEEE754 规定,有效数字第一位默认总是1 。因此,在表示精度的位数前面,还存在一个 “隐藏位” ,固定为 1 ,但它不保存在 64 位浮点数之中。也就是说,有效数字总是 1.xx...xx 的形式,其中 xx..xx 的部分保存在 64 位浮点数之中,最长为52位 。所以,JavaScript 提供的有效数字最长为 53 个二进制位,其内部实际的表现形式为:

    (-1)^符号位 * 1.xx...xx * 2^指数位

    这意味着,JavaScript 能表示并进行精确算术运算的整数范围为:[-2^53-1,2^53-1],即从最小值 -9007199254740991 到最大值 9007199254740991 之间的范围 。

    Math.pow(2, 53)-1 ; // 9007199254740991

    -Math.pow(2, 53)-1 ; // -9007199254740991

    可以通过 Number.MAX_SAFE_INTEGER 和  Number.MIN_SAFE_INTEGER 来分别获取这个最大值和最小值。

    console.log(Number.MAX_SAFE_INTEGER) ; // 9007199254740991

    console.log(Number.MIN_SAFE_INTEGER) ; // -9007199254740991

    对于超过这个范围的整数,JavaScript 依旧可以进行运算,但却不保证运算结果的精度。

    Math.pow(2, 53) ; // 9007199254740992

    Math.pow(2, 53) + 1; // 9007199254740992

    9007199254740993; //9007199254740992

    90071992547409921; //90071992547409920

    0.923456789012345678;//0.9234567890123456

    IEEE-745浮点数表示法数值精度丢失

    计算机中的数字都是以二进制存储的,二进制浮点数表示法并不能精确的表示类似0.1这样 的简单的数字

    如果要计算 0.1 + 0.2 的结果,计算机会先把 0.1 和 0.2 分别转化成二进制,然后相加,最后再把相加得到的结果转为十进制

    但有一些浮点数在转化为二进制时,会出现无限循环 。比如, 十进制的 0.1 转化为二进制,会得到如下结果:

    0.1 => 0.0001 1001 1001 1001…(无限循环)

    0.2 => 0.0011 0011 0011 0011…(无限循环)

    而存储结构中的尾数部分最多只能表示 53 位。为了能表示 0.1,只能模仿十进制进行四舍五入了,但二进制只有 0 和 1 , 于是变为 0 舍 1 入 。 因此,0.1 在计算机里的二进制表示形式如下:

    0.1 => 0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 101

    0.2 => 0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 001

    用标准计数法表示如下:

    0.1 => (−1)0 × 2^4 × (1.1001100110011001100110011001100110011001100110011010)2

    0.2 => (−1)0 × 2^3 × (1.1001100110011001100110011001100110011001100110011010)2

    在计算浮点数相加时,需要先进行 “对位”,将较小的指数化为较大的指数,并将小数部分相应右移:

    最终,“0.1 + 0.2” 在计算机里的计算过程如下:

    7c636d8f18d5

    经过上面的计算过程,0.1 + 0.2 得到的结果也可以表示为:

    (−1)0 × 2−2 × (1.0011001100110011001100110011001100110011001100110100)2=>.0.30000000000000004

    通过 JS 将这个二进制结果转化为十进制表示:

    (-1)**0 * 2**-2 * (0b10011001100110011001100110011001100110011001100110100 * 2**-52); //0.30000000000000004

    console.log(0.1 + 0.2) ; // 0.30000000000000004

    这是一个典型的精度丢失案例,从上面的计算过程可以看出,0.1 和 0.2 在转换为二进制时就发生了一次精度丢失,而对于计算后的二进制又有一次精度丢失 。因此,得到的结果是不准确的。

    几乎所有的编程语言浮点数都是都采用IEEE浮点数算术标准

    在C或者java里面,double是64位浮点数,float 是32 浮点数:  1bit符号  8bit指数部分 23bit尾数。推荐阅读《JAVA 浮点数的范围和精度》

    long与double在java中本身都是用64位存储的,但是他们的存储方式不同,导致double可储存的范围比long大很多

    long可以准确存储19位数字,而double只能准备存储16位数字(实际测试,是17位,)。double由于有exp位,可以存16位以上的数字,但是需要以低位的不精确作为代价。如果一个大于17位的long型数字存到double上,就会丢失数字末尾的精度

    如果需要高于19位数字的精确存储,则必须用BigInteger来保存,当然会牺牲一些性能。

    java 基本数据类型

    基本类型存储需求位数bit数取值范围取值范围

    byte1byte8bit1*8(8)-2^7~2^7-1-128~127

    short2byte16bit2*8(16)-2^15~2^15-1-32768~32767

    int4byte32bit4*8(32)-2^31~2^31-1-2147483648~2147483647

    long8byte64bit8*8(64)-2^63~2^63-1=-9223372036854775808~9223372036854775807

    float4byte32bit4*8(32)3.4028235E38~1.4E-453.4028235*10^38~1.4*10^-45

    double8byte64bit8*8(64)-2^1023~2^10241.7976931348623157*10^308~4.9*10^-324

    char2byte16bit2*8(16)2^16 - 1unicode编码范围

    java中char类型占2个字节、16位可以存放汉子,字母和数字占一个字节,一个字节8位,中文占2个字节,16位。

    在表中,long最大为=2^63-1,而double为2^1024,

    double是n*2^m(n乘以2的m次方)这种形式存储的,只需要记录n和m两个数就行了,m的值影响范围大,所以表示的范围比long大。

    但是m越大,n的精度就越小,所以double并不能把它所表示的范围里的所有数都能精确表示出来,而long就可以。

    float浮点数,小数点后第7位是部分准确的。例如,1.0000004就是1.00000035通过得到的,其实际保存和1.0000003相同。1.0000006也是通过舍入得到的。再往前第6位及以后均可以通过小数准确表示出来。通常说float数据的有效位是6~7位,也是这个原因。一般来说,无论是整数或者小数,用float表示时,从左边第一个非0的数字算起,从高到低的7位是准确的。此后的数位是不能保证精确的。

    double双精度浮点数小数部分有52位,和上面类似,最低6位(2^-52,2^-51,......)表示的规格化小数如下所示。从图中可以看出,双精度浮点数能准确表示到小数点后第15位,第16位部分准确。用double表示时,从左边第一个非0的数字起,从高到低的16位是准确的,此后的数位不一定精确

    尽管浮点数表示的范围很广,但由于精度损失的存在,加上幂次的放大作用,一个浮点数实际上是表示了周围的一个有理数区间。如果将浮点数绘制到一个数轴上,直观上看,靠近0的部分,浮点数出现较密集。越靠近无穷大,浮点数分布越稀疏,一个浮点值代表了周围一片数据。如下图所示。从这个意义上来说,浮点数不宜直接比较相等,它们是代表了一个数据范围。实际应用中,如果要使用浮点数计算,一定要考虑精度问题。在满足精度要求的前提下,计算结果才是有效的。

    在计算精度要求情形下,例如商业计算等,应该避免使用浮点数,严格采取高精度计算。

    7c636d8f18d5

    浮点数丢失解决方案

    我们常用的分数(特别是在金融的计算方面)都是十进制分数1/10,1/100等。或许以后电路设计或许会支持十进制数字类型以避免这些舍入问题。在这之前,你更愿意使用大整数进行重要的金融计算,例如,要使用整数‘分’而不是使用小数‘元’进行货比单位的运算

    即在运算前我们把参加运算的数先升级(10的X的次方)到整数,等运算完后再降级(0.1的X的次方)。

    在java里面有BigDecimal库,js里面有big.jsjs-big-decimal.js。当然BCD编码就是为了十进制高精度运算量制。

    BCD编码

    BCD编码(一般指8421BCD码形式)亦称二进码十进数或二-十进制代码。用4位二进制数来表示1位十进制数中的0~9这10个数。一般用于高精度计算。比如会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免去使电脑作浮点运算时所耗费的时间。

    为什么采用二进制

    二进制在电路设计中物理上更易实现,因为电子器件大多具有两种稳定状态,比如晶体管的导通和截止,电压的高和低,磁性的有和无等。而找到一个具有十个稳定状态的电子器件是很困难的。

    二进制规则简单,十进制有55种求和与求积的运算规则,二进制仅有各有3种,这样可以简化运算器等物理器件的设计。另外,计算机的部件状态少,可以增强整个系统的稳定性。

    与逻辑量相吻合。二进制数0和1正好与逻辑量“真”和“假”相对应,因此用二进制数表示二值逻辑显得十分自然。

    可靠性高。二进制中只使用0和1两个数字,传输和处理时不易出错,因而可以保障计算机具有很高的可靠性

    我觉得主要还是因为第一条。如果比如能够设计出十进制的元器件,那么对于设计其运算器也不再话下。

    JS数字精度丢失的一些典型问题

    两个简单的浮点数相加

    0.1 + 0.2 != 0.3 // true

    toFixed 不会四舍五入(Chrome)

    1.335.toFixed(2) // 1.33

    再问问一个问题 :在js数字类型中浮点数的最高精度多少位小数?(16位 or 17位?……why?

    JavaScript 能表示并进行精确算术运算的整数范围为:[-2^53-1,2^53-1],即从最小值 -9007199254740991 到最大值 9007199254740991 之间的范围。'9007199254740991'.length//16

    IEEE754 规定,有效数字第一位默认总是1 。因此,在表示精度的位数前面,还存在一个 “隐藏位” ,固定为 1 ,但它不保存在 64 位浮点数之中。也就是说,有效数字总是 1.xx...xx 的形式,其中 xx..xx 的部分保存在 64 位浮点数之中,最长为52位 。所以,JavaScript 提供的有效数字最长为 53 个二进制位

    let a=1/3

    a.toString();//"0.3333333333333333"

    a.toString();.length//18

    a*3===0.3333333333333333*3===1

    0.3333333333333332*3!==1

    相关链接:

    展开全文
  • 在C语言中float类型在数据输出是可能由于精度原因导致出错,所以可以参考本标准。 ,
  • VC6.0浮点数转INT4转化代码
  • IEEE754.PDF (berkeley.edu)http://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF 百度网盘分享链接 链接:https://pan.baidu.com/s/1KMaDNi04Q0ZzlNkxkONZ9w 提取码:1fwc 一些题外话: ...

     

    原文外网链接

    IEEE754.PDF (berkeley.edu)http://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF

    百度网盘分享链接

    链接:https://pan.baidu.com/s/1KMaDNi04Q0ZzlNkxkONZ9w 
    提取码:1fwc

    一些题外话:

    在线浮点数转换1

    Float (IEEE754 Single precision 32-bit) Converter (binaryconvert.com)http://www.binaryconvert.com/convert_float.html

    在线浮点数转换2

    IEEE-754 Floating Point Converter (h-schmidt.net)https://www.h-schmidt.net/FloatConverter/IEEE754.html

    我们常用的编程语言例如C#其采用的float也是采用此标准。

    stm32的keil编程也是采用此标准。

    有时候我们需要判断一个数是否是无效的浮点数,

    union
    
    {
    
        uint32 uint32byte;
    
        fp32 fp32byte;
    
    }byte4;
    
    bool check(fp32 dt)
    
    {
        
    
        byte4 tmp;
    
        tmp.fp32byte = dt;
    
        return  ((tmp.uint32byte & 0x7F800000) == 0x7F800000 );
    
    }

    可以参考

    (24条消息) 1.#QNAN stm32单片机浮点数处理_anlog的专栏-CSDN博客https://blog.csdn.net/anlog/article/details/119872410?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163670422116780274156757%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=163670422116780274156757&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_v2~rank_v29-2-119872410.pc_v2_rank_blog_default&utm_term=stm32&spm=1018.2226.3001.4450

    或者参考

    (24条消息) 打印浮点数输出 1.#IND 1.#INF nan inf 等解决_youqika的专栏-CSDN博客https://blog.csdn.net/youqika/article/details/18351901?utm_source=blogxgwz6&utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-8.no_search_link&spm=1001.2101.3001.4242.5

    特此记录

    anlog

    2021年11月12日

    展开全文
  • labview int32 转换 float函数VI 符合 IEEE 754标准,适合8.6版本的labview 使用
  • 目录htmlIEEE 754标准 浮点格式可分为符号位s,指数位e以及尾数位f三部分。其中真实的指数E相对于实际的指数有一个偏移量,因此E的值应该为e-Bias,Bias(127)即为指数偏移量。这样作的好处是便于使用无符号数来代替...

    目录html

    IEEE 754标准

    965ed0e588ab8adaa8c9df9567431958.png

    浮点格式可分为符号位s,指数位e以及尾数位f三部分。

    其中真实的指数E相对于实际的指数有一个偏移量,因此E的值应该为e-Bias,Bias(127)即为指数偏移量。这样作的好处是便于使用无符号数来代替有符号的真实指数。尾数f字段表明纯粹的小数,它的左侧即为小数点的位置。规格化数的隐藏位默认值为1,不在格式中表达。内存

    在IEEE-754 标准下,浮点数一共分为:get

    NaN:即Not a Number。非数的指数位所有为1 同时尾数位不全为0。在此前提下,根据尾数位首位是否为1,NaN 还能够分为SNaN 和QNaN 两类。前者参与运算时将会发生异常。

    无穷数:指数位所有为1 同时尾数位全为0。大。

    规格化数:指数位不全为1 同时尾不全为0。此时浮点数的隐含位有效,其值为1。

    非规格化数:指数位全为0 且尾数位不全为0。此时隐含位有效值变为0。另外须要注意,以单精度时为例,真实指数e并不是0-127=-127,而是-126,这样一来就与规格化下最小真实指数e=1-127=-126 达成统一,造成过渡。非规格化数隐函位表示为了0,此时表示的数据更小,提升了精度(0.1和1.1,隐含位是0的表示的更小)。

    0 :指数位与尾数位都全为0,根据符号位决定正负。

    0b2b96badacc5e3a02e34d0978e02657.png

    float的范围

    注意:指数的范围是-126~127,不是咱们认为的-127~128 ,这个是IEEE-754标准中定义的。循环

    (1)正数最大值以下:二进制

    高地址----------------------------->低​地址

    0 (1111 1110)( 111 1111 1111 1111 1111 1111)

    当咱们令指数位为:1111 1110 =254 (此处不能是1111 1111=255,1111 1111是NaN),则指数为254-127=127

    尾数位全为1,则最大数为1.11111111111111111111111*2^127=(2-2^-23)*2^127=3.4028*10^38,正规格化数中的最大。其中1.111 1111 1111 1111 1111 1111+ 0.000 0000 0000 0000 0000 0001=2,0.000 0000 0000 0000 0000 0000=2-2^{-23}

    当符号位为1时,是表示绝对值最大的负数

    高地址----------------------------->低​地址

    1(1111 1110)( 111 1111 1111 1111 1111 1111)

    表示-3.40*10^38

    因此范围是-3.40*10^38 到 3.40*10^38

    (2) float最小值(除0之外的最小值)

    高地址----------------------------->低​地址

    0 (0000 0001)(000 0000 0000 0000 0000 0001)

    当咱们令指数位为:0000 0001 =1(此处不能是0000 0000=0,指数全零是非规格化数)则指数为1-127=126

    为:1.0000 0000 0000 0000 0000 001*2^-126= 1.175e-038

    float精度

    float 类型的数据精度取决于尾数,首先是在不考虑指数的状况下23位尾数能表示的范围是[0, 2^23−1],实际上尾数位前面还隐含了一个"1",因此应该是一共24位数字,所能表示的范围是[0, 2^24-1](由于隐含位默认是"1",因此表示的数最小是1不是0),看到这24位能表示的最大数字为2^{24}-1,换算成10进制就是16777215,那么[0, 16777215]都是能精确表示的

    16777215 这个数字能够写成1.1111111 11111111 1111111 * 2^{23},因此这个数能够精确表示,而后考虑更大的数16777216,由于正好是2的整数次幂,能够表示1.0000000 00000000 00000000 * 2^{24}因此这个数也能够精确表示,在考虑更大的数字16777217,这个数字若是写成上面的表示方法应该是 1.0000000 00000000 00000000 1 * 2^{24},可是这时你会发现,小数点后尾数位已是24位了,23位的存储空间已经没法精确存储,这时浮点数的精度问题也就是出现了。

    看到这里发现 16777216 貌似是一个边界,超过这个数的数字开始不能精确表示了,那是否是全部大于16777216的数字都不能精确表示了呢?其实不是的,好比数字 33554432 就能够就能够精确表示成1.0000000 00000000 00000000 * 2^{25},说到这里结合上面提到的float的内存表示方式,咱们能够得出大于 16777216 的数字(不超上限),只要能够表示成小于24个2的n次幂相加,而且每一个n之间的差值小于24就可以精确表示。换句话来讲全部大于 16777216 的合理数字,都是[0, 16777215]范围内的精确数字经过乘以2^n获得的,同理全部小于1的正数,也都是 [0, 16777215] 范围内的精确数字经过乘以2^n获得的,只不过n取负数就能够了。

    16777216 已经被证明是一个边界,小于这个数的整数均可以精确表示,表示成科学技术法就是1.6777216 * 10^{7},从这里能够看出一共8位有效数字,因为最高位最大为1不能保证全部状况,因此最少能保证7位有效数字是准确的,这也就是常说float类型数据的精度。

    float小数

    从上面的分析咱们已经知道,float可表示超过16777216范围的数字是跳跃的,同时float所能表示的小数也都是跳跃的,这些小数也必须能写成2的n次幂相加才能够,好比0.五、0.2五、0.125…以及这些数字的和,像5.2这样的数字使用float类型是没办法精确存储的,5.2的二进制表示为101.0011001100110011001100110011……最后的0011无限循环下去,可是float最多能存储23位尾数,那么计算机存储的5.2应该是101.001100110011001100110,也就是数字 5.19999980926513671875,计算机使用这个最接近5.2的数来表示5.2。关于小数的精度与刚才的分析是一致的,当第8位有效数字发生变化时,float可能已经没法察觉到这种变化了。

    读取小数存储的原始值(举例)

    stm32 中小数存储计算

    counter+=0.001;

    if(counter==0.01)//该条件永远不会成立,十进制小数转换二进制的问题致使,应该转换为大于等于或者小于等于

    asda=*(vu32*)&counter;可经过该句读取counter在内存中的存储的数据;

    asda=*(vu32*)&counter;取counter地址,指针类型强制转换成vu32*,而后*取内容。

    0.01为0x3C23D70A,转换成2进制

    0011 1100 0010 0011 1101 0111 0000 1010

    符号位 0 表明正数

    指数011 1100 0  为120  (120-127)=-7,小数点左移动7。(若是是130则130-127=3,表示小数点右移动三位。)

    尾数01000111101011100001010  左边有一个能够理解的二进制点。此数字从浮点数的存储形式中省略。在尾数的开头加上1和二进制点可获得如下值:

    1.0100 0111 1010 1110 0001 0100 左移7位为0.0000 0010 1000 1111 0101 1100 0010 1000

    转换为十进制0.00999999977648258

    实际在watch窗口中观察写入0.01为0.00999999978(被四舍五入了)

    展开全文
  • IEEE 754标准--维基百科

    千次阅读 2020-03-13 22:37:23
    IEEE二进制浮点数算术标准IEEE 754) 是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number),一些特殊数值...

    IEEE二进制浮点数算术标准(IEEE 754) 是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number),一些特殊数值((无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”;它也指明了四种数值舍入规则和五种例外状况(包括例外发生的时机与处理方式)。

    IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。只有32位模式有强制要求,其他都是选择性的。大部分编程语言都提供了IEEE浮点数格式与算术,但有些将其列为非必需的。例如,IEEE 754问世之前就有的C语言,现在包括了IEEE算术,但不算作强制要求(C语言的float通常是指IEEE单精确度,而double是指双精确度)。

    该标准的全称为IEEE二进制浮点数算术标准(ANSI/IEEE Std 754-1985),又称IEC 60559:1989,微处理器系统的二进制浮点数算术(本来的编号是IEC 559:1989)[1]。后来还有“与基数无关的浮点数”的“IEEE 854-1987标准”,有规定基数为2跟10的状况。现在最新标准是“ISO/IEC/IEEE FDIS 60559:2010”。

    在六、七十年代,各家计算机公司的各个型号的计算机,有着千差万别的浮点数表示,却没有一个业界通用的标准。这给数据交换、计算机协同工作造成了极大不便。IEEE的浮点数专业小组于七十年代末期开始酝酿浮点数的标准。在1980年,英特尔公司就推出了单片的8087浮点数协处理器,其浮点数表示法及定义的运算具有足够的合理性、先进性,被IEEE采用作为浮点数的标准,于1985年发布。而在此前,这一标准的内容已在八十年代初期被各计算机公司广泛采用,成了事实上的业界工业标准。加州大学伯克利分校的数值计算与计算机科学教授威廉·卡韩被誉为“浮点数之父”。

    浮点数剖析

    一个浮点数 (Value) 的表示其实可以这样表示:
    在这里插入图片描述

    也就是浮点数的实际值,等于符号位(sign bit)乘以指数偏移值(exponent bias)再乘以分数值(fraction)。

    以下内文是IEEE 754对浮点数格式的描述。

    本文表示比特的约定

    把W个比特(bit)的数据,从内存地址低端到高端,以0到W−1编码。通常将内存地址低端的比特写在最右边,称作最低有效位(Least Significant Bit, LSB),代表最小的比特,改变时对整体数值影响最小的比特。声明这一点的必要性在于X86体系架构是小端序的数据存储。

    对于十进制整数N,必要时表示为N10以与二进制的数的表示N2相区分。

    对于一个数,其二进制科学计数法表示下的指数的值,下文称之为指数的实际值;而根据IEEE 754标准对指数部分的编码的值,称之为浮点数表示法指数域的编码值

    整体呈现

    IEEE 754浮点数的三个域
    二进制浮点数是以符号数值表示法的格式存储——最高有效位被指定为符号位(sign bit);“指数部分”,即次高有效的e个比特,存储指数部分;最后剩下的f个低有效位的比特,存储“有效数”(significand)的小数部分(在非规约形式下整数部分默认为0,其他情况下一律默认为1)。
    在这里插入图片描述

    指数偏移值

    在这里插入图片描述

    采用指数的实际值加上固定的偏移值的办法表示浮点数的指数,好处是可以用长度为$e}e个比特的无符号整数来表示所有的指数取值,这使得两个浮点数的指数大小的比较更为容易,实际上可以按照字典序比较两个浮点表示的大小。

    这种移码表示的指数部分,中文称作阶码。

    规约形式的浮点数

    如果浮点数中指数部分的编码值在 0 < e x p o n e n t ⩽ 2 e − 2 0<exponent\leqslant 2^{e}-2 0<exponent2e2之间,且在科学表示法的表示方式下,分数 (fraction) 部分最高有效位(即整数字)是 1,那么这个浮点数将被称为规约形式的浮点数。“规约”是指用唯一确定的浮点形式去表示一个值。

    由于这种表示下的尾数有一位隐含的二进制有效数字,为了与二进制科学计数法的尾数(mantissa)相区别,IEEE754称之为有效数(significant)。

    举例来说,双精度 (64-bit) 的规约形式浮点数在指数偏移值的值域为 00000000001 00000000001 00000000001(11-bit) 到 11111111110 11111111110 11111111110 ,在分数部分则是 000.....000 000.....000 000.....000 111.....111 111.....111 111.....111 (52-bit)

    非规约形式的浮点数

    如果浮点数的指数部分的编码值是0,分数部分非零,那么这个浮点数将被称为非规约形式的浮点数。一般是某个数字相当接近零时才会使用非规约型式来表示。 IEEE 754标准规定:非规约形式的浮点数的指数偏移值比规约形式的浮点数的指数偏移值小1。例如,最小的规约形式的单精度浮点数的指数部分编码值为1,指数的实际值为-126;而非规约的单精度浮点数的指数域编码值为0,对应的指数实际值也是-126而不是-127。实际上非规约形式的浮点数仍然是有效可以使用的,只是它们的绝对值已经小于所有的规约浮点数的绝对值;即所有的非规约浮点数比规约浮点数更接近0。规约浮点数的尾数大于等于1且小于2,而非规约浮点数的尾数小于1且大于0。

    特殊值

    这里有三个特殊值需要指出:
    在这里插入图片描述
    以上规则,总结如下:
    在这里插入图片描述

    32位单精度

    单精度二进制小数,使用32个比特存储。
    在这里插入图片描述
    S为符号位,Exp为指数字,Fraction为有效数字。 指数部分即使用所谓的偏正值形式表示,偏正值为实际的指数大小与一个固定值(32位的情况是127)的和。采用这种方式表示的目的是简化比较。因为,指数的值可能为正也可能为负,如果采用补码表示的话,全体符号位S和Exp自身的符号位将导致不能简单的进行大小比较。正因为如此,指数部分通常采用一个无符号的正数值存储。单精度的指数部分是−126~+127加上偏移值127,指数值的大小从1~254(0和255是特殊值)。浮点小数计算时,指数值减去偏正值将是实际的指数大小。

    单精度浮点数各种极值情况: 在这里插入图片描述

    64位双精度

    双精度二进制小数,使用64个比特存储。
    在这里插入图片描述
    S为符号位,Exp为指数字,Fraction为有效数字。指数部分即使用所谓的偏正值形式表示,偏正值为实际的指数大小与一个固定值(64位的情况是1023)的和。采用这种方式表示的目的是简化比较。因为,指数的值可能为正也可能为负,如果采用补码表示的话,全体符号位S和Exp自身的符号位将导致不能简单的进行大小比较。正因为如此,指数部分通常采用一个无符号的正数值存储。双精度的指数部分是−1022~+1023加上1023,指数值的大小从1~2046(0(2进位全为0)和2047(2进位全为1)是特殊值)。浮点小数计算时,指数值减去偏正值将是实际的指数大小。

    浮点数的比较

    浮点数基本上可以按照符号位、指数域、尾数域的顺序作字典比较。显然,所有正数大于负数;正负号相同时,指数的二进制表示法更大的其浮点数值更大。

    浮点数的舍入

    任何有效数上的运算结果,通常都存放在较长的寄存器中,当结果被放回浮点格式时,必须将多出来的比特丢弃。 有多种方法可以用来运行舍入作业,实际上IEEE标准列出4种不同的方法:

    舍入到最接近:舍入到最接近,在一样接近的情况下偶数优先(Ties To Even,这是默认的舍入方式):会将结果舍入为最接近且可以表示的值,但是当存在两个数一样接近的时候,则取其中的偶数(在二进制中是以0结尾的)。
    朝+∞方向舍入: 会将结果朝正无限大的方向舍入。
    朝-∞方向舍入: 会将结果朝负无限大的方向舍入。
    朝0方向舍入: 会将结果朝0的方向舍入。

    浮点数的运算与函数
    标准运算

    下述函数必须提供:
    在这里插入图片描述

    建议的函数与谓词

    在这里插入图片描述

    精度

    在二进制,第一个有效数字必定是“1”,因此这个“1”并不会存储。

    讨论一

    单精和双精浮点数的有效数字分别是有存储的23和52个位,加上最左手边没有存储的第1个位,即是24和53个位。

    log ⁡ 2 24 = 7.22 \log 2^{24}=7.22 log224=7.22
    log ⁡ 2 53 = 15.95 \log 2^{53}=15.95 log253=15.95
    由以上的计算,单精和双精浮点数可以保证7位和15位十进制有效数字。

    讨论二

    C++语言标准定义的浮点数的十进制精度(decimal precision):十进制数字的位数,可被(浮点数)表示而值不发生变化[3]。C语言标准定义的浮点数的十进制精度为:十进制数字的位数q,使得任何具有q位十进制数字的浮点数可近似表示为b进制的p位数字并且能近似回十进制表示而不改变这q位十进制数字[4]

    但由于相对近似误差不均匀,有的7位十进制浮点数不能保证近似转化为32比特浮点再近似转化回7位十进制浮点后保持值不变:例如8.589973e9将变成8.589974e9。这种近似误差不会超过1比特的表示能力,因此(24-1)*std::log10(2)等于6.92,下取整为6,成为std::numeric_limits::digits10以及FLT_DIG的值。std::numeric_limits::max_digits10的值为9,含义是必须9位十进制数字才能区分float的所有值;也即float的最大表示区分度。

    类似的,std::numeric_limits<double>::digits10或DBL_DIG是15, std::numeric_limits<double>::max_digits10是17

    例子

    以下的C++程序,概略地展示了单精和双精浮点数的精度。

    #include <iostream>
    
    int main () {
        std::cout.precision(20);
        float a=123.45678901234567890;
        double b=123.45678901234567890;
        std::cout << a << std::endl;
        std::cout << b << std::endl;
        return 0;
    }
    
    // Xcode 5.1
    // Output:
    // 123.456787109375
    // 123.45678901234568059
    // Program ended with exit code: 0
    

    全文由维基百科翻译-- 维基百科,自由的百科全书

    展开全文
  • IEEE754标准转换

    千次阅读 2020-09-14 22:50:38
    IEEE754标准 点此进入维基百科 类型 数符 阶码 尾数 总位数 短浮点数 1 8 23 32 长浮点数 1 11 52 64 求真值步骤: 写成二进制形式 按格式划分数符S、阶码E、尾数M 进行移位
  • 基于IEEE754标准 将一个十六进制转换为十进制浮点数的小工具,提供C#源码
  • 根据IEEE754标准用C#实现32位16进制转浮点数 IEEE754标准的转化公式为:V=(-1)^s*2^E*M
  • IEEE754标准浮点数转换

    千次阅读 2020-12-07 16:31:13
    IEEE754标准浮点数转换 IEEE754标准是一种浮点数表示标准,一般分为单、双精度两种,单精度是32位的二进制数,双精度是64位的二进制数,一个浮点数的组成分为三个部分。 ①第1位是数符s,s=1表示负数,s=0表示正数...
  • 浮点数IEEE754标准

    2018-08-25 20:34:41
    2008-IEEE754浮点数标准文件,英文版本 共11章节,包含浮点数格式、运算等
  • 以一个具体的float值为例,Java中的float值采用的是IEEE754中的单精度标准,使用32个比特进行存储。例如: 0100 0100 1010 0110 1001 1110 0000 0000 其中: 0100 0100 1010 0110 1001 1110 0111 0100 第一位的0为...
  • IEEE754标准的浮点数存储格式

    千次阅读 2019-06-03 12:07:14
    IEEE754标准的浮点数存储格式 https://www.cnblogs.com/MikeZhang/p/IEEE754FloatEncode20180117.html https://github.com/WebAssembly/nontrapping-float-to-int-conversions 操作系统 : CentOS7.3.1611_x64 ...
  • 工控行业通讯485常用modbus协yi,通讯的数据遵循IEEE754协yi存储,为了方便使用,对modbus通讯数据进行处理。
  • 我们的PC计算机其实存储浮点数为IEEE 754标准,如下所示: 1.本文部分素材来源网络,版权归原作者所有,如涉及作品版权问题,请与我联系删除; 2.未经原作者允许不得转载本文内容,否则将视为侵权; 3.转载或者...
  • 本设计是基于fpga的浮点乘法器设计,两个浮点数用ieee754标准表示,程序采用的verilog语言
  • Convertor按照IEEE 754标准对Float和Double类型进行转换
  • 网上搜索了一下,发现有很多人在搜索这个转换的。但没有一个有互换功能,所以就自己手动写了一个,拿给有需要的人;IEEE754浮点数转整数;整数转浮点数的源码,
  • IEEE754标准浮点数的转换

    千次阅读 2020-03-04 16:29:32
    IEEE754标准浮点数的转换 对于一个十进制的的数字,当我们需要转化为浮点数时需要按照一定的规则,而IEEE754是现在应用比较广泛的一种标准,下面是关于该标准的一些转化规则。 浮点数表示的格式: 单精度:总位数...
  • 1985年IEEE(Institute of Electrical and Electronics Engineers)提出了IEEE754标准。该标准规定基数为2,阶码E用移码表示,尾数M用原码表示,根据二进制的规格化方法,最高数字位总是1,该标准将这个1缺省存储,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,374
精华内容 6,149
关键字:

ieee754标准

友情链接: htmlToPdf.rar