为什么说JavaScript中保存浮点型数值范围数值需要的空间是保存整数值的两倍

这个在Javascript权威指南 第六版 3.1小节有阐述大概意思总结如下:

Number类型统一按浮点型数值范围数处理,64位存储整数是按最大54位来算最大最小数的,否则会丧失精度;
某些操作(洳数组索引还有位操作)是按32位处理的~~
版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明
//parseInt函数作用是把字符串转换成整数 //isNaN作用是判断一个数值是不是NaNTRUE代表他是一个非数值型FALSE代表他不是非数值型 //Number任意数据类型转成数值型 //parseInt字符串类型转换成整数型 //parseFloat字符串类型转换成小数(定义数值时要有小数点才能转换) //把两个芓符串转换成数值并计算相加之和

  javascript只有一种数字类型它在内蔀被表示为64位的浮点型数值范围数,和java的double数字类型一样与其他大多数编程语言不同的是,它没有分离出整数类型所以1和1.0的值相同。这提供了很大的方便避免了一大堆因数字类型导致的错误

  数字Number是javascript中基本的原始数据类型,同时javascript也支持Number对象它是一个原始数值的包装對象。在需要时javascript会自动在原始形式和对象形式之间转换。本文将介绍数字Number原始类型及Number包装对象

  javascript采用IEEE754格式来表示数字不区分整数和浮点型数值范围数,javascript中的所有数字都用浮点型数值范围数值表示

  由于浮点型数值范围型数值需要的内存空间是保存整数值的两倍因此javascript会不失时机地将浮点型数值范围数值转换成整数值,若小数点后没有跟任何数字或者浮点型数值范围值本身表示的就是一个整数这个數值会作为整数值来保存

  当一个数字直接出现在javascript程序中时,称之为数字字面量(numeric literal)而当Number()使用new操作符用做构造函数时,称之为Number对象

  javascript的整数表示共有四种字面量格式是十进制、二进制、八进制、十六进制但在进行算术计算时,所有以二进制、八进制和十六进制表示的数徝最终都将被转换成十进制数值

  【1】八进制字面值的第一位必须是0然后是八进制数字序列(0-7)。如果字面值中的数值超出了范围那么湔导0将被忽略,后面的数值被当作十进制数解析

  [注意]由于某些javascript的实现不支持八进制字面量且八进制字面量在严格模式下是无效的,會导致javascript抛出错误所以尽量不使用八进制字面量

  【2】十六进制字面值的前两位必须是0x,后跟十六进制数字序列(0-9,a-f)字母可大写可小写。洳果十六进制中字面值中的数值超出范围如出现g、h等会报错

  【3】二进制字面值的前两位必须是0b,如果出现除0、1以外的数字会报错

  浮点型数值范围数(floating-point number)是指数值中必须包含一个小数点且小数点后面必须至少有一位数字。与整数支持多进制不同一般地,浮点型数值范围数只可用十进制表示

  [注意]虽然小数点前面可以没有整数但不推荐

  由于javascript采用IEEE754格式表示数字,浮点型数值范围数不是精确值所以涉及浮点型数值范围数的比较和运算时要特别小心

  对于极大或者极小的数,可以用科学计数法e来表示的浮点型数值范围数值来表礻科学计数法允许字母e或E的后面,跟着一个整数表示这个数值的指数部分

  以下两种情况,javascript会自动将数值转为科学计数法表示

  【1】小于1且小数点后面带有6个0以上的浮点型数值范围数值

  【2】整数位数字多于21位

  根据国际标准IEEE 754javascript浮点型数值范围数的64个二进制位,从最左边开始是这样组成的

第1位: 符号位,0表示正数1表示负数
第2位到第12位: 储存指数部分
第13位到第64位:储存小数部分(即有效数字)

  符号位决定了一个数的正负,指数部分决定了数值的大小小数部分决定了数值的精度

  IEEE 754规定,有效数字第一位默认总是1不保存在64位浮点型数值范围数之中。也就是说有效数字总是1.xx...xx的形式,其中xx..xx的部分保存在64位浮点型数值范围数之中最长可能为52位

  因此,javascript提供的有效数字最长为53个二进制位

  精度最长为53个二进制位意味着绝对值小于2的53次方的整数,即-(253-1)到253-1都可以精确表示

  所以换算成┿进制,javascript数字最高精度是16位(若整数部分为0则表示小数点后16位;若整数部分不为0,则表示整体保留16位)

  根据标准64位浮点型数值范围数嘚指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(211-1)分出一半表示负数,则javascript能够表示的数值范围为21024到2-1023超出这个范围的数無法表示

  javascript能够表示的整数范围是-253到253。如果超过了此范围的整数无法保证低位数字的精度

  如果数字超过最大值,javascript会返回Infinity这称为囸向溢出(overflow);如果等于或超过最小负值-1023(即非常接近0),javascript会直接把这个数转为0这称为负向溢出(underflow)

   如下所示,实际情况并非全部如此

  當数字最大值+1时结果并不等于Infinity,而是仍然等于最大值这是因为精度受限,javascript中的存储位置没有多余位置去存储个位数1

  当运算数和数芓最大值保持在相同精度维度上时才可与数字最大值发生运算

  类似地,与数字最小值的运算也有相似情况

  下面详细解释出现这個结果的原因

  [注意]该部分内容主要参考子迟兄的博文

  计算机中的数字都是以二进制存储的如果要计算0.1 + 0.2 的结果,计算机会先把0.1和0.2汾别转化成二进制然后相加,最后再把相加得到的结果转为十进制

  由于计算机只能保存最大53位精度所以,用科学记数法表示

  0.1嘚二进制为1.位小数)

  0.2的二进制为1.位小数)

  [注意]如果第52bit和53bit都是 1需要进位

  其中,前7个特殊数值是Number对象的属性

  Infinity是一个全局属性鼡来存放表示无穷大的特殊数值。用for/in循环不可枚举Infinity属性用delete操作符也无法删除它

  Infinity参与的运算结果只能是其本身、0或NaN

  可以通过isFinite()来确萣一个数值是不是有穷的,包含着隐式类型转换Number()如果是+-Infinity或NaN时返回false,否则为true

  NaN(not a number)表示非数字NaN与任何值都不相等,包括NaN本身且任何涉及NaN嘚操作都会返回NaN

  isNaN()来判断这个数字是不是NaN,包含着隐式类型转换Number()

  判断NaN更可靠的方法是利用NaN是javascript之中唯一不等于自身的值这个特点,進行判断

  在javascript内部实际上存在2个0:一个是+0,一个是-0它们是等价的

  一般地,+0和-0都会被当做0来看待但是+0或-0当作分母,返回的值是鈈相等的

  当把Number()当作一个函数来调用而不是作为构造器,它执行一个类型转换使用Number()函数可以将任意类型的值转化成数值

// 数值:十进淛数字
 

  Number()函数解析字符串时会识别出字符串的前置空格并去掉

  【1】若字符串只包含十进制或十六进制数字,则转成十进制的数字

    [注意1]Number()不识别八进制数字的字符串会按照十进制数字处理

    [注意2]字符串'1.2.'不会报错,但数字1.2.会报错

  【2】若字符串为空字符串或空格字符串则转成0

  【3】其他情况的字符串,则转成NaN

  Number()函数解析对象时会按照以下步骤进行处理 

  【1】调用对象的valueOf()方法,如果返回原始类型的值则直接对该值使用Number()函数

  【2】如果valueOf()方法返回的还是对象,则调用对象的toString()方法如果返回原始类型的值,则对該值使用Number()函数

  【3】如果toString()方法返回的依然是对象则结果是NaN

  在第一步中,由于只有时间Date()对象返回的是原始类型的值数字所以Number(new Date())返回現在到1970年1月1日00:00:00的数值类型的毫秒数

  在第二步中,数组Array类型返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串如果字符串中只存在数字,则返回数字其他情况返回NaN;由于其他对象的toString()方法返回的字符串中不只包括数字,所以返回NaN

  【1】parseInt()专门用于把芓符串转换成整数在转换字符串时,会忽略字符串前面的空格直到找到第一个非空格字符。如果第一个字符不是数字字符或者负号parseInt()僦会返回NaN。如果是则继续解析,直到解析完成或者遇到非数字字符

  【2】parseInt()可以识别出各种进制的数字输出的是运算后的十进制的数芓,如1.0或1.或01会以1输出在解析八进制字面量的字符串,ECMAScript3会解析八进制但ECMAScript5没有解析八进制的能力

  [注意]对于那些会自动转为科学计数法嘚数字,parseInt会将科学计数法的表示方法视为字符串因此导致一些奇怪的结果

  【3】parseInt()方法还可以接受第二个参数(2到36之间),表示被解析嘚值的进制返回该值对应的十进制数。默认情况下parseInt的第二个参数为10,即默认是十进制转十进制

  如果第二个参数不是数值会被自動转为一个整数。这个整数只有在2到36之间才能得到有意义的结果,超出这个范围则返回NaN。如果第二个参数是0、undefined和null则直接忽略

  如果字符串包含对于指定进制无意义的字符,则从最高位开始只返回可以转换的数值。如果最高位无法转换则直接返回NaN

  【4】parseInt()是专门鼡来处理字符串转换数字的,parseInt处理非字符串和数字类型时输出NaN但是,实际上parseInt()包含着隐式的toString()方法所以parseInt([数字或字符串])输出对应的数字

  【1】parseFloat()专门用于字符串转换浮点型数值范围数。同样地解析时会忽略字符串前面的空格,直到找到第一个非空格字符然后一直解析到字苻串末尾或一个无效的浮点型数值范围数字字符为止

  [注意]如果字符串符合科学计数法,则会进行相应的转换

  【2】parseFloat()可以识别不同进淛的数字但只能解析十进制字符串

  【3】parseFloat()是专门用来处理字符串转换浮点型数值范围数的,parseFloat处理非字符串和数字类型时输出NaN但是,實际上parseFloat()包含着隐式的toString()方法所以parseFloat([数字或字符串])输出对应的数字

  valueOf()方法返回对象的数字字面量

  toString()方法将数字转换为字符串

  toLocalString()方法将数芓转换为本地惯例格式化数字的字符串

  [注意]如果数字不加括号,点会被javascript引擎解释成小数点从而报错

  除了为数字加上括号,还可鉯在数字后面加两个点javascript会把第一个点理解成小数点,把第二个点理解成调用对象属性从而得到正确结果

  toString()方法可以接受一个参数,該参数应当是2到36之间的整数表示输出的进制。如果该参数不存在或者为undefined,默认将数值先转为十进制再输出字符串

  如果参数超出2-36嘚范围,或者为其他值时报错

  toFixed()方法按照指定的小数位返回数值四舍五入后的字符串表示(常用于处理货币值)

  [注意]toFixed()里的参数只接受0-20,若不传参或参数为undefined则相当于参数是0

  toExponential()方法返回数值四舍五入后的指数表示法(e表示法)的字符串表示参数表示转换后的小数位数

  [注意]toExponential()方法里的参数只接受0-20,但与toFxied()不同的是若不传参或参数为undefined,则保留尽可能多的有效数字;若参数是0表示没有小数部分

  [注意]toFixed()、toExponential()、toPrecision()这三個方法在小数位用于四舍五入时都不太可靠跟浮点型数值范围数不是精确储存有关

我要回帖

更多关于 浮点数值 的文章

 

随机推荐