js中Number中的浮点数存储

191 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情

10进制浮点转为二进制方法

将整数绝对值以短除法除2转为二进制,

小数采用乘2取整,顺序排列

即,将小数每次乘2,之后将整数作为当前位的数值,剩余小数参与下一次运算。

eg

具体存储方式【IEEE 754标准】

总体存储大榄

当浮点为32位,阶码为8位。为64位时阶码为11位

所有浮点数都可以使用e计数法表示

具体存储方式就是将十进制的浮点数转为二进制,之后将二进制的浮点数的小数点进行偏移同时增加e值【初始为0】。偏移至小数点左边只有一位。

因为偏移后小数点左边必是一个1,所以该1已确定就不用再在计算机存储,默认存在即可,那么只用存储e的阶码以及小数点后面的数值【称为尾数】

符号位记录符号情况,阶码位记录e的阶码数,尾数位记录偏移后小数点后面的数值

阶码存储

存储方式

阶码使用偏置常数的方法存储。偏置常数的设定为2^(n-1) - 1【n为阶码位数】

以阶码存储位为8举例。

原来阶码为8位存储位,总的存储范围应为0~255,偏置常数为127

但是有特殊值:所有位为0 以及 所有位为1,是特殊值,具体之后讲解。

所以数的表示范围为1~254

偏置常数法:阶码要表示的数+127 = 阶码在计算机中存储的数。

目的:处理负指数情况。

所以总存储范围应该减去127,就变成了-126~127.

尾数部分就存储偏移【指的是二进制将小数点左移至小数点左边剩一位】后的数值的小数部分。

尾数部分存储的是数值的绝对值的原码

注意

浮点数的尾数存储的是数值的绝对值,负数并不是存储补码,而是绝对值原码

值的类别【IEEE 754】

格式化值

浮点数存储的阶码既不全为0也不全为1的时候为格式化值。此时隐含位有效,数值为1

【所谓隐含位就是之前提到的小数点前被隐藏的那一位】

用IEEE 754的存储方式可表示正常的的数值

特殊数值

+0与-0

阶码与尾数位全为0,符号用符号位决定

NaN:非数字

阶码每位为1,尾数位不全为0.

REM是取余

rem和mod唯一的区别在于:x%y

    当x和y的正负号一样的时候,两个函数结果是等同的;当x和y的符号不同时,rem函数结果的符号和x的一样,而mod和y一样。

正负无穷INF

尾数位为0,阶码全为1,符号由符号位决定

用于表示计算中的上溢问题。eg:两极大数相乘。结果可能大到无法保存为浮点数,必须进行舍入操作。根据IEEE标准,此时不能将结果舍入为可以保存的最大浮点数,因为无意义,故舍入为无穷。

*当要输出一个上溢的数据时,printf会显示 *inf或infinity

非格式化

当阶码全为0,且尾数位不全为0,此时隐含位有效,值为0

提供一种数值0的表示方法,因为格式化数尾数的表示要求是大于等于1的,所以格式化数不能表示0。

用于表示接近于0的数,即正下溢和负下溢。

浮点数误差分析

舍入错误

给定一个特别大的数【eg:2e20】加1,之后再减去原先的数,最后结果在理论上为1,但是实际上计算机输出的却并不是1.

原因就是这个浮点类型的小数位数,并不够精确计算所需。所以在计算中进行了舍入,最后算出的结果自然就不如我们所盼

无法与0进行直接比较

由于误差所以与0直接进行比较是逻辑上的错误表示。

应该设置一个比较小的数用来表示精度,当与0的差值小于这个精度的时候,就说明该浮点数等于0,反之小于0

句末语

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 N 天,点击查看活动详情