• js数值类型


    js数值类型--number

    更详细的参考资料

    中文wiki-IEEE754
    中文wiki-IEEE754(免翻墙版)

    js数值类型的存储形式

    JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此.

    • 什么是浮点数?
      利用科学计数法来表达实数(Number),即用一个尾数/小数部分(Fraction),一个基数(Base,通常为2),一个指数(Exponent)以及一个表示正负的符号(Sign)来表达实数。尾数有时也称为有效数字(Significand)
      浮点数表示公式:在这里插入图片描述
      其存储结构为:在这里插入图片描述
      各部分说明:
    • 符号域Sign:决定数值的正负
    • 指数域Exponent:决定数值的小数点位置
    • 指数偏移值(修正值)Bias:为了使指数域区分正负(小数点既可右移,也可左移),而在存储时默认减掉的一个值,64位浮点数该值为1023=(1/2)*2指数域位数-1=210-1(因为初始值从0开始,所以减去1)
    • 小数域/有效数字域Fraction:小数点之后的有效数字(未与指数域相乘之前)

    但是,同一个数值,由于指数域的取值不同会有不同的表示方法,例:12.34=1.234×101=0.1234×102.为了提高数据的表示精度同时保证数据表示的唯一性,需要对浮点数做规格化处理。
    在计算机内,对非0值的浮点数,要求尾数的绝对值必须大于基数的倒数,即|F|≥1/B.对于二进制来说,就是:要求尾数域的最高有效位应为1,把不满足这一表示要求的尾数,变成满足这一要求的尾数的操作过程,叫作浮点数的规格化处理,通过尾数移位和修改阶码实现规格化要求。


    js数值的范围与精度(有效数位数)

    一般情况下(normalized,0< E< 2047)
    js数值类型表示整数的范围

    • js数值中,整数都可以被精确存储;而很多小数的存储会有误差(见后续章节)
    • 由以上js数值的存储结构:有效数字有53位(一个隐含位),也就是说,绝对值小于2的53次方的整数,即-2^53 到 2^53的整数,都可以精确表示.
    • 注:js能精确表示的最大数值是253 ,但可以表示的最大数值不是 253.

    特殊情况下

    • 情况1:denormalized(非规约形式的浮点数: 有效数字隐含位,也就是浮点数整数部分=0,E=0,0<F<1)

    [N=(-1)^s imes({color{Red} 0}+F) imes2^{{color{Red} 0}-(Bias-1)} ]

    此种情况下,有效数字的隐含位(小数点之前)由1变为0且计算公式变为:±0.F×2(-1022)
    [注意:denormalized下,E取0,但指数域不是-1023而是-1022.]

    • 情况2:零值(E=0,F=0)
      由于符号位S是独立存储的,所以由+0和-0之分.
    • 情况3:infinity无穷大(E=2047,F=0)
      同零值,也有+∞和-∞之分.
    • 情况4:NaN(not a number)(E=2047,F>0)

    注:

    • 正向溢出(overflow):一个数>=2^1024,返回infinity
    • 反向溢出(underflow):一个数小于2^(-1075)(指数部分最小的-1023加上52位小数部分),返回0.

    js中能表示的最大值与最小值(绝对值)
    在这里插入图片描述

    • 最大值Number.MAX_VALUE

      如上图,最大值应该是仅次于infinity的值,也就是E=2046,F为全1时的值,因此:
      Number.MAX_VALUE=1×(2^1023)×1.1....1=1×2^(1023-52)×11....1B=2^(1023-52)×9007199254740991≈1.7976931348623157e+308

    • 最小值Number.MIN_VALUE

      最小值应该是指数域E=0,而小数域F仅有最低位为1时的值.属于denormalized,因此根据其公式:
      Number.MIN_VALUE=1×2^(-1022)×2^(-52)≈5e-324


    js中十进制小数的存储与运算不准确的问题

    知识回顾:十进制转二进制

    • 正整数部分:除二取余,倒序排列
      在这里插入图片描述

    • 小数部分:乘二取整,正序排列
      在这里插入图片描述

    十进制小数转二进制小数的问题
    一些小数,例如0.1,0.2,0.3,0.4等,在转换为二进制时,其位数是无穷的,而我们用于存储的空间只有52位,所以要进行舍入,那么就会产生误差.

    举例 0.1+0.2===0.3为false

    • 首先,我们用在线任意进制转换器对0.1,0.2进行十进制到二进制转换:
      0.1D=0.00011001100110011001100110011001100110011001100110011010B
      0.2D=0.00110011001100110011001100110011001100110011001100110100B
      0.3D=0.010011001100110011001100110011B
      (注意:上述三个十进制小数对应的二进制数位数本身是无穷,我们对此作了第52位的舍入,即截取前52位,并在第52位上加1)

    • 接着我们对上述0.1和0.2两行二进制数进行二进制加法运算,得到如下结果:
      0.01001100110011001100110011001100110011001100110011001110

    • 再借由在线任意进制转换器将结果转换回十进制,得到结果为:
      0.3000000000000000444089209850062616169452667236328125.

    同时,我们运行js代码:
    alert((0.1+0.2));
    得到结果为:
    在这里插入图片描述
    总结:
    我们在键盘输入一个十进制数值后,js会将之进行十进制到二进制的转换并存储,在此过程中产生了误差,等到我们再次使用这个值的时候,它已经不是原来正确的值了.

    解决办法(简单但不严谨):
    将要计算的小数转换为整数进行计算,计算完毕后再转换回小数(只适用于四则运算).


    数值的表示方法

    • 字面量直接表示:

      • 十进制:35
      • 二进制:10010B或者前缀0b(数字0,字母b)
      • 八进制:前缀0(数字0).如果有前缀0,其后又有8,9视为十进制
      • 十六进制:前缀0x(数字0,字母x/X)
    • 科学计数法:(以下两种情况,js自动转换为科学计数法)

      • 小数点前数字多于21位
      • 小数点后的零多于5个

    关于js中的NaN

    • NaN不是数据类型,只是基本类型number里的特殊值
    • NaN不等于任何值,包括它本身
    • NaN转换为布尔值为false
    • 用isNaN(x)方法判断一个值是否是NaN(注意:isNaN只针对数值,传入非数值参数可能会出现问题)

    与数值有关的全局方法

    • parseInt(str):将字符串转换为整数
      转换说明:

    • 自动过滤前导的空格

    • 如果参数不是字符串,会先将其转换为字符串,再进行操作

    • 转换过程是一个一个字符逐个进行,遇到不能转换为数字的字符,返回已经转换的部分;如果第一个字符都不能转换,返回NaN

    • 字符串以0开头,按十进制转换;以0x或0X开头,按16进制转换

    • 遇到自动转换为科学计数法的数字字符串,parseInt()会将其科学计数法表示的形式作为字符串进行转换,从而产生古怪的结果.

      第二参数:

    • parseInt(str)还可以接受第二个参数(2-36),指明被解析值的进制,返回该值对应的十进制数;

    • 若第二个数值超出2-36范围,返回NaN

    • 第二个数值为0,null,undefined,直接忽略

    • 如果第二个参数为非数值,先将之转换为数值,再按前两个情况判断和操作

    • 如果第一个参数包含对于指定进制无意义的字符,只返回可转换的部分(若最高位无法转换,返回NaN)

    • parseFloat(str):将字符串转换为浮点数
      转换说明:

    • 自动过滤字符串前导空格

    • 如果参数不是字符串或者字符串第一个字符不能转换,返回NaN(此处与parseInt不同)

    • 转换过程是一个一个字符逐个进行,遇到不能转换为浮点数的字符,返回已经转换的部分

    • 会将空字符转换为NaN

    • isNaN(x):判断一个值是否为NaN
      转换说明:

    • isNaN()只对数值精准有效,如果传入非数值,会先将其转为数值,再进行判断:isNaN('123')==false;isNaN('abc')==true;isNaN(Array)/isNaN(Object)==true

    • 但是,对于空数组和只有一个数值成员的数组,null,isNaN()返回false;不过,对于空对象{},返回true

    • 因此,判断NaN应该利用它是唯一一个"不等于自身的值"的特性来实现

    • isFinite():判断某个值是否为正常的数值

    • isFinite()只对数值精准有效,如果传入非数值,会先将其转为数值,再进行判断.

    • 但是,对于空数组和只有一个数值成员的数组,null,isNaN()返回true;不过,对于空对象{},返回false

    • 对于Infinite,-Infinite,NaN,undefined返回false

  • 相关阅读:
    PHP 8.0 带来的新特性
    do sth 之 提取了一份文档
    Java入门15---网络编程
    Java入门14---logback
    限流策略
    JConsole 可视化工具
    SpringBoot注解---6.声明式事务
    SpringBoot注解---5.AOP
    SpringBoot注解---4.扩展原理
    SpringBoot注解---2.组件赋值
  • 原文地址:https://www.cnblogs.com/peterzhangsnail/p/13192591.html
Copyright © 2020-2023  润新知