Skip to content

Number 类型

Number 类型的存储

在 JavaScript 中 Numebr 类型遵循的是 IEEE 754 规范中的 64 位双精度浮点数(Java 的 Double 也是遵循此规范)。

IEEE 754 规范

img

小知识:

精度符号位指数位(阶符)尾数位总位数
单精度182332
双精度1115264
长双精度1156480

符号位: 0 :正数 1:负数

指数位:11 位指数 => -1023 - 1024( (1-2^10) 到 2^10)

为什么 11 位却是使用 2^10 的范围?

尾数: 52 位

1 的二进制码
js
// 二进制
1
// 符号位为 0 ,指数位为0
1.000000
// 移位到首位为1
1.000000 * 2^0 // 没有移位
// 符号位为 0 ; 指数位为 1023+0 => 01111111111 尾数位 : 00000000...
0 01111111111 000000000000(52位)
20.59375 的二进制码
js
20.59375
// 正数位
20 -> 10100
// 小数位 0.59375
0.59375 -> 10011
// 20.59375的二进制
10100.10011
// 符号位为 0 ,左偏移4位
1.010010011 * 2^4
// 符号位为 0 ; 指数位为 1023+4 => 10000000011 尾数位 : 010010011 00000...
0 10000000011 010010011000(52位)
// 结果为:
01000000 00110100 10011000 00000000 00000000 00000000 00000000 00000000

问题

  1. 精度问题

十进制转换成二进制的时候可能存在尾数多余 52 位的情况,那将尾数多余 52 位的部分舍去也就会导致精度不准确。

著名的栗子: 0.1 + 0.2 === 0.3 // ?

原因

js
// IEEE 754中 0.1的二进制为
存储格式   : 0 01111111011 10011001100110011001011*13
转换成十进制: 0.000110011001(1001*11) => 0.09999999999999787
// 0.2
存储格式   : 0 01111111100 1001100110011001100
转换成十进制: 0.00110011001(1001*11) => 0.19999999999999574

image-20230210184205842

parseInt()

parseInt(string, radix) 解析一个字符串并返回指定基数的十进制整数,radix 是 2-36 之间的整数,表示被解析字符串的基数。

语法

js
parseInt(string, radix)

参数

  • string 要被解析的值。如果参数不是一个字符串,则将其转换为字符串 (使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。

  • radix 可选 从 2 到 36 的整数,表示进制的基数。例如指定 16 表示被解析值是十六进制数。如果超出这个范围,将返回 NaN。假如指定 0 或未指定,基数将会根据字符串的值进行推算。注意,推算的结果不会永远是默认值 10!文章后面的描述解释了当参数 radix 不传时该函数的具体行为。

返回值

  1. 从给定的字符串中解析出的一个整数。

  2. 或者 NaN,当

  • radix 小于 2 或大于 36,或 字符串中第一个下标的值大于基数
js
parseInt("14", 1) // NaN  基数1小于2
parseInt("14", 100) // NaN  基数100大于36
parseInt("34", 2) // NaN  字符串中第一个下标的值大于基数 3>2

parseInt("34", 3) // 3 第二个字符 4 > 3; 所以结果就是 3*3^0
parseInt("212412", 3) // 23 第四个字符 4 > 3; 所以结果就是 2*3^2 + 1*3^1 + 2*3^0 = 23
  • 第一个非空格字符不能转换为数字。

题目

  1. ["1","2","3"].map(parseInt) 的结果

拆分:

  • parseInt的入参为两个 : string : 字符串值 , radix: 基数
  • map 遍历的回调参数为3个 : value : 值 , index: 下标 , array: 原始数组

那么实际相当于

js
["1","2","3"].map((value , index) => parseInt(value , index))

// === 
[parseInt("1" , 0) , parseInt("2" , 1) , parseInt("3" , 2)] 
//  第一个基数为0,那么就按照字符串默认基数处理,这边是10。 结果为 1
//  第二个基数为1,基数小于2; 结果为N
//  第三个基数为2, 3>2,转换失败; 结果为N

// 最终结果为 : [1 , NaN , NaN]
  1. Number.parseIntparseInt 的区别

参考

  1. https://www.cnblogs.com/vickylinj/p/14495155.html