资讯专栏INFORMATION COLUMN

IEEE754 浮点数格式 与 Javascript number 的特性

BigTomato / 767人阅读

摘要:类型使用的就是标准中的双精度浮点数。数字的许多特性都依赖于此标准,例如令人费解的不等于这篇文章介绍标准中双精度浮点数二进制储存格式,并由此推出中数字的一些特性。

Javascript 作为一门动态语言,其数字类型只有 number 一种。 nubmer 类型使用的就是 IEEE754 标准中的 双精度浮点数。Javascript 数字的许多特性都依赖于此标准,例如令人费解的 0.1+0.2不等于0.3

这篇文章介绍 IEEE754 标准中双精度浮点数二进制储存格式,并由此推出 js 中数字的一些特性。

一、IEEE754 中浮点数的储存格式

在 IEEE754 中,双精度浮点数储存为64位:

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

浮点数表示的值的形式由 $e$ 和 $f$ 确定:

二、根据 IEEE754 计算 0.1+0.2 1. 将 0.1 使用转换为二进制

$0.1 = (0.0dot0dot0dot1dot1)_2=(-1)^0 imes2^{-4} imes(1.dot1dot0dot0dot1)_2$

$0.2 = 0.1 imes2^1=(-1)^0 imes2^{-3} imes(1.dot1dot0dot0dot1)_2$

由于小数位 $f$ 仅储存 52bit, 储存时会将超出精度部分进行"零舍一入"

值类型 小数位(储存范围内) 小数位(储存范围外)
无限精确值 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001...
实际储存值 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010 -

由于计算加减时不会对指数位进行位运算,这里不计算指数位的表示,直接使用数字表示最终的指数值

0.1、0.2 的表示如下:

浮点数数值 符号位 $s$ 指数值 $E$ 小数位 $f$
0.1 0 -4 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010
0.2 0 -3 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010
2. 将 0.1 与 0.2 相加

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

$0.1 ightarrow (-1)^0 imes2^{-3} imes(0.1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101 0)_2$
$0.2 ightarrow (-1)^0 imes2^{-3} imes(1.1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010)_2$

$0.1 + 0.2 = (-1)^0 imes2^{-2} imes(1.0011001100110011001100110011001100110011001100110100)_2$

可以通过下面的方法检验计算结果是否于 js 中一致:

0.1 + 0.2 === (-1)**0 * 2**-2 * (0b10011001100110011001100110011001100110011001100110100 * 2**-52)
//> true
//计算正确
三、计算 javascript Number 的特性

在js中 Number对象上附带了许多属性,表示可数的范围等信息,例如 Number.MAX_SAFE_INTEGER 是一个16位的数字,这一部分将解释如何计算出这些有特殊意义的数字。

1.计算 Number.MAX_VALUENumber.MIN_VALUE

当符号位为0、指数取到1023、小数位全为1时,为可表示的最大值
当符号位为0、指数位全为0(表示非规格浮点数)、小数位仅最后一位为1时,为可表示的最小正值

var max = (-1)**0 * 2**1023 * (Number.parseInt( "1".repeat(53) ,2) * 2**-52);
max === Number.MAX_VALUE;
//> true

var min = (-1)**0 * 2**-1022 * (Number.parseInt( "0".repeat(52)+"1" ,2) * 2**-52);
min === Number.MIN_VALUE;
//> true
2.计算 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER

Number.MAX_SAFE_INTEGER 表示最大安全整数,它是9开头的16位数字,也表明js number最大精度不超过16位。

ECMASCRIPT-262 定义:

The value of Number.MAX_SAFE_INTEGER is the largest integer n such that n and n + 1 are both exactly representable as a Number value.
http://www.ecma-international...

改变指数位为53,这让每个小数位都表示浮点数的整数部分,小数位最低位对应 $2^0$,然后将每个小数位都置1,可得最大准确整数:

var max_safe_int = (-1)**0 * 2**52 * (Number.parseInt("1".repeat(53),2) * 2**-52);
max_safe_int === Number.MAX_SAFE_INTEGER;
//> true
//当它 +1 时,可由 (-1)**0 * 2**53 * (Number.parseInt("1"+"0".repeat(52),2) * 2**-52) 正确表示,而再 +1 时则无法准确表示

//符号位取反可得最小安全整数
-1 * max_safe_int === Number.MIN_SAFE_INTEGER;
3.计算 Number.EPSILON

Number.EPSILON 是一个极小值,用于检测计算结果是否在误差范围内。例如:

Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON;
//> true

//2017-9-27 补充
1.1 + 1.3 - 2.4 < Number.EPSILON
//> false

根据 ECMASCRIPT-262 定义:

The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1 that is representable as a Number value, which is approximately 2.2204460492503130808472633361816 x 10‍−‍16.

http://www.ecma-international...

根据定义Number.EPSILON是大于1的最小可表示数与1的差,可以据此计算出 Number.EPSILON 的值:

//将表示1的二进制小数位的最左端置1,可表示大于1的最小数
var epsilon = (-1)**0 * 2**0 * (Number.parseInt("1"+"0".repeat(51)+"1",2) * 2**-52) - 1;
// (-1)**0 * 2**0 * (+`0b1${"0".repeat(51)}1` * 2**-52) - 1;
epsilon === Number.EPSILON;
//> true

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81417.html

相关文章

  • 该死IEEE-754点数,说「约」就「约」,你底线呢?以JS名义来好好查查你

    摘要:而的浮点数设置的偏移值是,因为指数域表现为一个非负数,位,所以,实际的,所以。这是因为它们在转为二进制时要舍入部分的不同可能造成的不同舍 IEEE 754 表示:你尽管抓狂、骂娘,但你能完全避开我,算我输。 一、IEEE-754浮点数捅出的那些娄子 首先我们还是来看几个简单的问题,能说出每一个问题的细节的话就可以跳过了,而如果只能泛泛说一句因为IEEE754浮点数精度问题,那么下文还是...

    gaosboy 评论0 收藏0
  • 数字在JavaScript中是如何编译

    摘要:数字数字都是浮点数,按照标准进行存储。因此,只有偶数可以在范围内表示。但只有超过指数的上限才称为中的溢出。结论在这篇博文中,我们研究了如何将其浮点数转换为位。 JavaScript中的所有数字都是浮点数。这篇博客文章解释了这些浮点数如何在64位二进制内部表示。由于特别考虑,本文中的数字将用整数表示,以便在阅读本文后,您将了解在以下交互中会发生什么: (译者注:浮点数并不一定等于小数,定...

    Moxmi 评论0 收藏0
  • 深度剖析0.1 +0.2===0.30000000000000004原因

    摘要:吐槽一句,大二的专业课数字逻辑电路终于用在工作上了。,整数位为,且精度只到十分位,因此是。如果是不限精度的话,转换后的二进制数应该是无限循环。再看一下百科给出的标准因此,的类型,最高的位是符号位,接着的位是指数,剩下的位为有效数字。 showImg(https://segmentfault.com/img/remote/1460000011902479?w=600&h=600); 用一...

    haobowd 评论0 收藏0
  • JS-Number—了解IEEE双精度点数

    摘要:一复习进制转进制整数部分除取余,逆序小数部分乘取整,正序在线工具二了解双精度浮点数规范通过进制的科学计数法存储。最终可表示为图片来源其中,,都是实际存储科学计数法的值。 一、复习10进制转2进制 1)整数部分:除2取余,逆序2)小数部分:乘2取整,正序在线工具 二、了解IEEE 754双精度浮点数规范 1) 通过2进制的科学计数法存储。 和10进制的科学计数法类似,二进制的科学技术法格...

    shixinzhang 评论0 收藏0
  • JavaScript四舍五入那些坑

    摘要:进制之谜众所周知,计算机在设计之初,出于各方面角度考虑,最终采用二进制的格式来存储数据。同样的情况,也会出现在十进制和二进制的转换中。当我们在计算机中,声明一个变量为,其实该数字作为二进制保存在计算机中,并不真的是。 前言 经常使用JavaScript用来处理数字的程序员都知道,JavaScript的Number.toFixed,这一函数,在格式化数字时,会自动进行四舍五入,例如: 1...

    zollero 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<