文章目录

  • JavaScript数字类型详解
    • 前言
    • 数字的写法
      • 分隔符
      • 省略的0
      • 十六、八、二进制
    • toString(base)
    • 舍入
    • 精度
    • 偏差
      • 偏差现象
      • 偏差原因
      • 解决方法
    • Infinity、NaN
    • Object.is
    • parseInt、parseFloat
    • Math对象
    • 总结

JavaScript数字类型详解

你真的完全了解JavaScript数字类型吗,看完这篇在回答我!

前言

JavaScript中存在两种表示数字的类型:

  1. Number类型,也就是常规意义上的数字类型,以64位的IEEE-754格式存储,属于“双精度浮点数”,截至目前,我们接触到的数字全部都是Number类型;
  2. BigInt类型,表示任意长度的整数,通常情况下我们用不到它们,除非表示 253 至 -253之外的数字,此类专业数据类型我们会在后面的章节详细介绍;

数字的写法

数字的写法本身很简单,但是JavaScrpt有很多方便快捷的语法糖供我们使用,好好学习这些语法糖不仅能够提高我们的代码阅读能力,同时可以提高我们代码的高级感(逼格)。

分隔符

十进制的数字最简单了,几乎每篇文章我们都多多少少会使用,例如我们创建一个变量,并存储100亿:

let tenbillion = 10000000000;

虽然操作起来非常简单,但是存在一个问题:很难数清楚1后面到底有几个0,如果我们写的是转账代码,错个0可能会倾家荡产。

此时,我们可以使用_作为分隔符,如下:

let tenbillion = 10_000_000_000;

上述代码就可以非常明白的数清0的个数,显然是最优解!

这里的下划线_就是JavaScript的一个语法糖,在执行过程中会被引擎忽略,以上两种写法效果完全相同,但是阅读体验相差很大。

清奇脑回路

有些童鞋就要问了,我从小都是40一组的,为啥非要30分一组呢?所以,我们可以写成下面的方式,同样没有问题:

let tenbillion = 100_0000_0000;

亦或者写成这样:

let tenbillion = 1_0000_0000_00;

这里我想表达的是,不论你采用哪种分割方式,都是不影响数字本身的大小的,快想一个逼格最高的方式吧!

省略的0

虽然使用_可以优雅的分割很多0,但是在实际生活中,我们一般不这么写,例如我们常常将10000000000写成“100亿”,这样就可以省略很多0,从而降低犯错的可能性。

JavaScript同样提供了一种省略0的写法,我们可以使用字母e后面跟个数字表示0的个数,举个栗子:

let tenbillion = 1e10;//100亿,1后面10个0
console.log(3.14e9);//3140000000,后面7个0,此处疑惑可往下看

上述代码的理解非常简单,e10可以理解为1_0000_0000_00,也就是1后面100,所以我们可以认为:

1e10 === 1 * 1_0000_0000_00;//e10表示1后面10个0
3.14e9 === 3.14 * 1_000_000_000;//e9表示1后面9个0

我们还可以使用这种方法表示非常小的数字,例如1纳米:

let nm = 0.000000001;//单位(米)

由于0的个数过多,我们也可以使用_分割:

let nm = 0.000_000_001;

当然,还可以使用e的方式省略掉所有的0,如下:

let nm = 1e-9;//1的左边9个0,包括小数点前面的那个

换句话说,e-9的意思就是1-9,也就是1/1000_000_000,所以下面的等式是成立的:

1e-9 === 1 / 1_000_000_000;
3.14e-8 === 3.14 / 1_000_000_00;

十六、八、二进制

十六进制是编程中常用到的格式,例如表示颜色、编码等,我们可以在普通数字前加0x表示十六进制数字:

let hex = 0xff;//255,不区分大小写,0xFF是一样的

二进制数字使用0b开头:

let bin = 0b1011;//11

八进制数字使用0o开头:

let oct = 0o777;//511

这种简便的写法只支持这三种特殊类型,至于其他进制的数字可以使用特殊的函数生成(parseInt)。

toString(base)

toString方法可以把数字转为对应进制base的字符串形式。

举个栗子:

let num = 996;
console.log(num.toString(8));//转为8进制字符串
console.log(num.toString(16));//转为16进制字符串
console.log(num.toString(32));//转为32进制字符串

代码执行结果如下:

base的范围可以从236,如果不填默认为10

注意,如果使用数字直接调用toString方法,在有些情况下需要是应用两个.,举例如下:

console.log(123.toString(8));//Error,语法错误
console.log(123..toString(8));//正确,173

数字后面有两个.,这是因为在JavaScript中数字后面的第一个.被认为是小数点,第二个点才是调用函数的.

如果是小数就不存在这个问题,举个栗子:

console.log(3.14.toString(8));

亦或者,我们使用小括号可以避免使用两个点,举个栗子:

console.log((123).toString(8));//'173

舍入

舍入是数字最常用的操作之一,通常包括:

  1. 向下取整,Math.floor(num)

    console.log(Math.floor(3.14));//3
    console.log(Math.floor(9.99));//9
    console.log(Math.floor(-3.14));//-4
    console.log(Math.floor(-9.99));//-10
    

    不遵循四舍五入原则,直接取小于等于当前数值的最近整数。

  2. 向上取整,Math.ceil(num)

    console.log(Math.ceil(3.14));//4
    console.log(Math.ceil(9.99));//10
    console.log(Math.ceil(-3.14));//-3
    console.log(Math.ceil(-9.99));//-9
    

    不遵循四舍五入原则,直接取大于等于当前数字的最近整数。

  3. 就近取整,Math.round(num)

    console.log(Math.round(3.14));//3
    console.log(Math.round(9.99));//10
    console.log(Math.round(-3.14));//-3
    console.log(Math.round(-9.99));//-10
    

    遵循四舍五入原则,取距离当前数字最近的整数。

  4. 移除小数,Math.trunc(num)

    console.log(Math.trunc(3.14));//3
    console.log(Math.trunc(9.99));//9
    console.log(Math.trunc(-3.14));//-3
    console.log(Math.trunc(-9.99));//-9
    

    直接移除小数点后面的数字,取整数位。IE浏览器不支持这个方法

对比以上四种方法:

Math.floor Math.ceil Math.round Math.trunc
3.14 3 4 3 3
9.99 9 10 10 9
-3.14 -4 -3 -3 -3
-9.99 -10 -9 -10 -9

精度

上述方法只是简单的把小数舍入成了整数,在有些情况下,我们需要特定精度的小数,例如取圆周率后4位应该怎么办呢?

有两种方法:

  1. 数学乘除计数

    let pi = 3.1415926;
    console.log(Math.round(pi * 10000) / 10000);//3.1416
    

    上述代码先将pi乘以10000,然后取整,再除以10000,从而得到了符合精度要求的结果。但是,这么做看起啦呆呆的,JavaScript为我们提供了更简单的方法。

  2. toFixed(n)

    let pi = 3.1415926;
    console.log(pi.toFixed(4));//3.1416
    

    以上代码看起来输出上没有什么问题,实际上,toFixed返回的是一个字符串,如果我们需要一个数字类型,要转换一下才行,可以使用单目运算符+ pi.toFixed(4)

    此外,如果小数的尾数长度不够,toFixed会在后面补上'0':

    let num = 3.1;
    console.log(num.toFixed(9));
    

    代码执行结果如下:

    这也侧面证明了toFixed的返回值是一个字符串,否则0会被省略。

偏差

浮点数表示在很多情况下总是存在偏差

在计算机内部,浮点数根据IEEE-754标准进行表示,其中单精度浮点数32位,双精度浮点数64位。在双精度浮点数中,1位用于表示符号,52位用于存储有效数字,11位存储小数点的位置。

偏差现象

虽然64位已经可以表示非常大的数字了,但是仍然存在越界的可能,例如:

let bigNum = 1e999;
console.log(bigNum);//Infinity

越过做最大值的数字将变为Infinity(无穷),这样就丢失了原有数字的大小,属于偏差的一种。

还有一种偏差,需要我们学习:

console.log(0.1+0.2 === 0.3);//false
console.log(0.1 + 0.2);

代码执行结果如下:

没错,0.1 + 0.2的结果并不是0.3,而是一堆0后面加个4

这种偏差是非常致命的,尤其在商城、银行工作场景中,即使是一个非常小的偏差,在高流水场景下都会丢失无尽的财富。

曾经听说过一个银行员工通过克扣工人工资,盗取百万财富的故事,每个员工的工资只克扣2毛!

我想这种事情发生在我身上,我肯定发现不了,所以无时无刻的精确是多么的重要。

这个故事不知真假~~

偏差原因

先以我们常见的十进制为例,我们都知道,小数中存在两个奇葩,一个叫无限循环小数,另一个叫无限不循环小数,例如1/3就是一个无限循环小数0.3333333(3),而圆周率就是一个无限不循环小数。无限就意味着无法用数字清楚的描述这个数字的大小,我们能写出来的都是不精确的。

二进制同样存在一些无限循环的数字,不同的是在十进制中0.1这种看起啦很简单的数字,在二进制中却是无限循环小数。

举个例子:

let x = 0.1;
console.log(x.toFixed(20));

代码执行结果如下:

是不是觉得不可思议呢?我们只是简单的创建了一个变量并赋值0.1,然后取小数点后20位,却得到了一个匪夷所思的结果。

如果我们换一个角度或许会更容易理解这种现象,在十进制中,任何整数除以10或者10整数次幂都是正常的精确的数字,例如1/10或者996/1000。但是,如果以3为除数,就会得到循环的结果,例如1/3

这种描述如果换到二进制上,同样是成立的。

在二进制中,任何整数除以2或者2的整数次幂都是正常的精确的数字,但是,如果以10为除数,就会得到无限循环的二进制数。

所以,我们就可以得出结论,二进制数字无法精确表示0.10.2就像十进制没有办法描述1/3一样。

注意:

这种数据上的偏差并非JavaScript的缺陷,像PHP、Java、C、Perl、Ruby都是同样的结果。

解决方法

  1. 舍入

    在展示一个无限循环小数的时候,我们可以直接使用toFixed方法对小数进行舍入,该方法直接返回字符串,非常方便用于展示价格。

    0.3.toFixed(2);//0.30
    
  2. 使用小单位

    另外一种方式是,我们可以使用较小的单位计算诸如价格、距离,例如采用分而不是元计算总价,实际上很多交易网站都是这么做的。但是这种方法只是降低小数出现的次数,并没有办法完全避免小数的出现。

Infinity、NaN

JavaScript数字中有两个特殊值:InfinityNaN

如何判断一个数字是不是正常数字呢?

我们可以使用两个方法:

  1. isFinite(val)
    该函数会将参数val转为数字类型,然后判断这个数字是否是有穷的,当数字不是NaNInfinity-Infinity时返回true

    console.log(isFinite(NaN));//false
    console.log(isFinite(Infinity));//false
    console.log(isFinite(3));//true
    console.log(isFinite('12'));//true
    

    代码执行结果如下:

    由于无法转为数字的字符串会被转为NaN,所以我们可以使用isFinite方法判断字符串是不是数字串:

    console.log(isFinite('xxxx'));//false
    console.log(isFinite('Infinite'));//false
    console.log(isFinite(' '));//true,空串转为0
    

    代码执行结果如下:

  1. isNaN(val)
    valNaN或者无法转为数字的其他值时,返回true

    console.log(isNaN(NaN));//true
    console.log(isNaN('Infinite'));//true
    

    代码执行结果:

    为什么要使用isNaN函数而不是直接判读呢?
    例如:

    console.log(NaN === NaN);//false
    

    代码执行结果如下:

    这是因为NaN不等于任何数,包括自身。

Object.is

Object.is(a,b)可以判断参数ab是否相等,若相等返回true,否则返回false,它的结果只有三种情况:

  1. 可以比较NaN

    console.log(Object.is(NaN,NaN));//true
    

    代码执行结果:

  2. 0 和 -0

    console.log(Object.is(0,-0));//false
    

    代码执行结果:

    在计算机内部,正负使用01表示,由于符号不同,导致0-0实际上是不同的,二者的表示方式也不一样。

  3. 其他
    ​ 其他比较情况和a === b完全相同。

parseInt、parseFloat

parseIntparseFloat可以把字符串转为数字,与+Number不同的是,二者的限制更为松散。例如,像"100¥"这样的字符串使用+Number必然返回NaN,而parseIntparseFloat却能轻松应对。

举个例子:

console.log(+"100¥");
console.log(parseInt("100¥"));
console.log(parseFloat("12.5¥"));

代码执行结果:

parseIntparseFloat会从字符串中读取数字,直到无法读取为止。二者特别适合处理像"99px""11.4em"这种数字开头的字符串情况,但是对于其他字符开头的字符串则返回NaN

console.log(parseInt('ff2000'));//NaN

但是,我们发现ff2000实际上是一个十六进制的数字字符串,parseInt同样可以处理这种情况,不过需要添加一个进制参数。

举个例子:

console.log(parseInt('FF2000',16));//16719872
console.log(parseInt('0xFF2000',16));//16719872
console.log(parseInt('nnnnnn',36));//1430456963

代码执行结果:

Math对象

内置的Math对象中包含了许多我们经常用到的常量和方法,以下仅举例介绍常用的几个:

  1. Math.PI

    圆周率Π是一个无限不循环的常量,我们可以使用Math.PI代替:

    console.log(Math.PI);
    

  2. Math.random()
    生成一个位于区间[0,1)的随机数:

    console.log(Math.random());
    console.log(Math.random());
    


如果我们需要一个特定区间内的随机数,可以乘以特定的值,然后取整哦。

  1. Math.pow(a,b)

    计算ab,举例如下:

    console.log(Math.pow(2,3));//8
    
  2. Math.max()/Math.min()

    从任意数量的参数中选出一个最大/最小值:

    console.log(Math.max(1,2,3,4,5));//5
    console.log(Math.min(1,2,3,4,5));//1
    

总结

  1. 使用_分割较长的数字;
  2. 使用e省略数字较多的0;
  3. 0x十六进制;
  4. 0o八进制;
  5. 0b二进制;
  6. parseInt(val,base)转字符串为数字,base取值区间为[2, 36]
  7. parseInt和parseFloat可以转以数字开头的字符串;
  8. toString(base)转数字为指定进制base的字符串,base取值区间为[2, 36];
  9. Math对象中内置的方法;

Math对象非常有用,建议多看看Math Doc。

28.精讲JavaScript数字类型,你不知道的必考点。相关推荐

  1. 视频教程-零基础JS入门系列课程(2)之JS语法基础精讲-JavaScript

    零基础JS入门系列课程(2)之JS语法基础精讲 螺钉课堂讲师,擅长Vue.React.ReactNative.NodeJS等前端框架及技术 邓老师 ¥59.00 立即订阅 扫码下载「CSDN程序员学院 ...

  2. 0基础学图论!——图论精讲/详细/新手理解概念必看!

    并不会有更好的阅读体验 特别特别感谢: lmpplmpplmpp大佬牺牲自己宝贵时间,为我没有脾气的耐心讲解. BeyondHeavenBeyondHeavenBeyondHeaven大佬,无偿帮我康 ...

  3. 中级软件测试笔试题100精讲_数字IC设计职位经典笔试面试100题(71~80)

    71.什么叫做OTP片(OTP(一次性可编程)).掩膜片,两者的区别何在? OTP与掩膜 OTP是一次性写入的单片机.过去认为一个单片机产品的成熟是以投产掩膜型单片机为标志的.由于掩膜需要一定的生产周 ...

  4. r语言 新增一列数字类型_R语言实战之R语言基础语法精讲(一)

    R是用于统计分析.绘图的语言和操作环境.R是属于GNU系统的一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具.在学习R数据科学之前,我们首先要对R语言的基础语法有一个良好的了 ...

  5. SAP ABAP 数字类型精讲

    ABAP/4有3种数字类型(数字型). (1)整数型 I ·值范围为-231-2147483648)~231-1(2147483647). ·只支持整数类型. ·非整数型数据会进行四舍五入(Round ...

  6. 2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原版笔记系列)

    2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原版笔记系列) 目录 2.7mnist手写数字识别之训练调试与优化精讲(百度架构师手把手带你零基础实践深度学习原 ...

  7. acm新手小白必看系列之(3)——暴力枚举精讲及例题

    acm新手小白必看系列之(3)--暴力枚举精讲及例题 暴力枚举说白了就是列举所有情况,然后一个一个排查. 这节多说无益直接上题(这节假的精讲) 1·大乐透 在小明曾经玩过的一种对号码的纸牌游戏(乐透) ...

  8. acm新手小白必看系列之(7)——快速幂取模精讲及例题

    acm新手小白必看系列之(7)--快速幂取模精讲及例题 性质1:(a+b)%m=(a%m+b%m)%m 性质2:(ab)%m=(a%mb%m)%m 给你一个数a,让你求其b次连乘后的结果 当b很小时, ...

  9. 【每日一题】8月28日题目精讲 编号

    [每日一题]8月28日题目精讲 编号 链接:https://ac.nowcoder.com/acm/problem/19925 来源:牛客网 题目描述 你需要给一批商品编号,其中每个编号都是一个7位1 ...

最新文章

  1. 扫描分发Apriori算法学习(一)
  2. 【TensorFlow】tf.nn.softmax_cross_entropy_with_logits 函数:求交叉熵损失
  3. 姓名性别电话邮箱html表单,HTML form标签语法、属性、规范和示例详细说明-立地货...
  4. 笔记之_java整理JavaScript
  5. linux+vim+动不了,linux的vim按了ctrl+s之后假死的解决办法
  6. 2021-2022元宇宙报告:化身与智造,元宇宙座标解析
  7. 开课吧:深入了解C++语言应用方向有哪些?
  8. 《几何与代数导引》习题1.34.1
  9. python中eval函数和str函数
  10. python wxpython常用控件实例
  11. 基于springboot汽车租赁系统
  12. 15款替代微软产品的开源软件
  13. linux下的c++filt 命令
  14. 推荐 4 款超好用的内网穿透工具,总有一款适合你
  15. 教你如何一键重装Windows7系统
  16. keybindings.json
  17. Lightroom Classic 9.0安装教程
  18. C++程序员发展方向有哪些?
  19. 来自一位双非本科大二学生的?自我救赎:堕落——蜕变
  20. 中国无人零售商店前景展望与未来发展预测分析报告2022-2028年版

热门文章

  1. 反反爬须知:AES加密和解密
  2. VS2017下载安装C#版本jieba库
  3. TextView设置最大行数、或者最多显示6个字、结束时为省略号
  4. 仙人掌之歌——系统设计(3)
  5. 一篇很搞笑的高考作文
  6. 医学信息学相关英语缩写含义
  7. 配置Hi提醒的定时提醒任务,微信短信提醒还不够?那就直接打电话吧
  8. JS笔记(一) ECMAScript部分
  9. Uncaught TypeError: Cannot set properties of undefined (setting ‘ innerHTML ) 问题
  10. Microsoft推出适用于Win 8.1和Win10的KB 4010250 Flash Player更新