越努力,越幸运,做个ccode~

0%

JS数据类型-Number类型

前言

最近在做题目LeetCode表示数值的字符串这道题的时候
对数值类型又有了新的认识 打算重新总结下

1. 整数、浮点数

JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1与1.0是相同的,是同一个数 1 === 1.0 // true

保留两位小数

1 四舍五入

1
var num = 2.446242342
2
num = num.toFixed(2)     // 输出是字符串 需要用parseFloat或Number再转一下

2 不四舍五入

1
Math.floor(15.7784514000 * 100) / 100       // 15.77

2. 数值的进制

  • 十进制:没有前导0的数值

  • 八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值

    012  // 10
    0o12 // 10
    0O12 // 10
    078  // 78   超出范围 无效的八进制 解析为十进制
  • 十六进制:有前缀0x或0X的数值

    0xA   // 10
    0x12  // 18
    0XAB  //171
  • 二进制:有前缀0b或0B的数值

    0b111 // 7
    0B11  // 3

默认情况下,JavaScript 内部会自动将八进制、十六进制、二进制转为十进制

3. 进制之间的转换

1) Number.prototype.toString([radix])

toString() 方法返回指定 Number 对象的字符串表示形式。
radix 指定要用于数字到字符串的转换的基数(从2到36)。如果未指定 radix 参数,则默认值为 10。

1
(12).toString()   // "12"   十进制转十进制
2
(012).toString()  // "10"     八进制转十进制
3
(10).toString(2)  // "1010"   十进制转二进制
4
(0b1010).toString(8)  // "12"  二进制转八进制

toString()以后是字符串格式 在通过格式转换 转为数值类型就好啦 怎么转换,后续有介绍哦

2) parseInt(string,[radix])

parseInt() 可以将任意进制的数转为10进制

1
parseInt(111,2) // 3
2
parseInt(12,8)  // 10
3
parseInt(0xA)   // 10  
4
parseInt(014)   // 12

关于parseInt()的详细解释在后面

4. Number() 函数

在说NaN 之前先说下Number函数

Number() 函数是数值类型的构造函数 同时也可以将其他类型转为数值类型
如果无法转为数值 就返回NaN

Number()函数的转换规则如下

  • Boolean false => 0 true => 1

  • Number 直接返回

  • null => 0

  • undefined => NaN

  • 字符串
    1 空字符串转为0
    2 只包含数字(包含前导正负号) 将其转为十进制
    3 如果包含有效的进制格式 将转为相同大小的十进制
    4 如果包含有效的浮点格式 将其转为对应的浮点数值
    5 如果不符合以上条件 返回NaN

  • 对象 调用对用的valueOf()方法 然后按照前面的规则进行转换 如果转换的结果是NaN 则调用对象的toString()方法,然后再依照前面的规则进行转换

    Number(false)      // 0 布尔值false对应0
    Number(123)        // 123 数值类型直接返回
    Number(null)       // 0
    Number(undefined)  // NaN
    Number('')         // 0
    Number('abc')      // NaN 'abc' 不能被转为数字
    Number('123')      // 123  '123' 可以被转为数字
    Number('123a)      // NaN  '123a' 不是只包含数字不能被转换
    Number('0x12')     // 18    0x12是有效的进制格式 站位10进制
    Number('1.1')      // 1.1   有效的浮点格式 转为相应的浮点格式
    
    Number([])        // 0   因为[].toString() ==> ''  Number('') ==> 0 
    Number([2])       // 2   因为[2].toString() ==> '2' Number('2') ==> 2
    Number([1,2,3])   // NaN  [1,2,3].toString() ==> '1,2,3' 不能转为数值
    
    Number({})        // NaN   ({}).toString() ==> "[object Object]"  不能转为数值

所以对于leetCode 这道题我们可以利用Number()函数对于字符串的转换规则 如果结果是NaN 就不符合条件 否则就是可以转为数值的字符串

1
var isNumber = function (s) {
2
  s = s.trim()
3
  if (s == '') return false  // 因为 Number('') === 0 所以需要做特殊判断
4
  return !isNaN(Number(s))
5
}

5. NaN

NaN 表示“非数字”(Not a Number) 是一个特殊的数值 数据类型依然属于Number

  • 主要出现在将字符串解析成数字出错的场合
  • 一些数学函数的运算结果会出现NaN 比如 0除以0也会得到NaN
  • NaN不等于任何值,包括它本身

针对NaN的特性 ES定义了isNaN()函数 该函数接受一个参数 可以为任何类型 isNaN()会尝试将这个参数转为数值 转换规则与Number()函数一致 所以isNaN方法可以用来判断一个值是否 “不是数值”

NaN === NaN  // false
isNaN(NaN)   // true
isNaN(123)   // false

// isNaN()只对数值有效,如果传入其他值,会先转成数值类型
isNaN('')             // false
isNaN('hello')        // true
//相当于
isNaN(Number('hello')) //true

isNaN(false)           // false  false会转为0
isNaN({})              //true
isNaN([1,2])           //true
// 所以isNaN() 为true的时候,有可能是一个字符串,或对象或数组
// 所以使用isNaN()时,需要先判断下数据类型
// 但是当数组为空,或数组长度为1时返回false
isNaN([]) //false
isNaN([1]) //false

由于isNaN()函数会对参数进行转换 那这题又可以直接写为

1
var isNumber = function (s) {
2
  s = s.trim()
3
  if (s == '') return false  // 因为 Number('') === 0 所以需要做特殊判断
4
  return !isNaN(s)
5
}

6. parseInt()

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

parseInt 参数

parseInt(string,[radix]) 接受两个参数

  • string 如果参数不是字符串类型 会通过toString()方法转为字符串
  • radix 从2-36 表示字符串的基数 需要注意的是 10不是默认值

如果 radix 是 undefined、0或未指定的,JavaScript会假定以下情况:

  • 如果输入的 string以 “0x”或 “0x”(一个0,后面是小写或大写的X)开头,那么radix被假定为16,字符串的其余部分被当做十六进制数去解析。
  • 如果输入的 string以 “0”(0)开头, radix被假定为8(八进制)或10(十进制)。具体选择哪一个radix取决于实现。ECMAScript 5 澄清了应该使用 10 (十进制),但不是所有的浏览器都支持。因此,在使用 parseInt 时,一定要指定一个 radix。
  • 如果输入的 string 以任何其他值开头, radix 是 10 (十进制)。
1
parseInt(110,2)  // 6 二进制110 转为十进制是 6
2
parseInt(123,8)  // 83 八进制的123 转为十进制是83
3
parseInt(89,8)   // NaN 不是合法的八进制
4
parseInt('014')  // 14  被当做十进制解析
5
parseInt(014)    // 12  因为(014).toString() => 12

一道有意思的面试题

1
["1", "2", "3"].map(parseInt)  // [1,NaN,NaN]
2
// 相当于parseInt(1,0)  => 1 string不以任何其他值开头 radix为十进制 parseInt(1,10) => 1
3
// parseInt(2,1) => NaN  1进制不合法 所以返回NaN 
4
// parseInt(3,2) => NaN  3 是不合法的二进制 所以返回NaN

parseInt 忽略后续字符

如果 parseInt 遇到的字符不是指定 radix 参数中的数字,它将忽略该字符以及所有后续字符,并返回到该点为止已解析的整数值。 parseInt 将数字截断为整数值。 允许前导和尾随空格。

1
parseInt('123a',2) // 1 因为符合二进制的只有1 
2
parseInt('1123110',2)  // 3  符合二进制的只有前面的11 找到2不符合 会忽略后面的字符 解析为十进制为3
3
parseInt('123abc')     // 123 这通常用来在字符串中提取前面的数值

7. parseFloat()

parseFloat() 函数解析一个参数(必要时先转换为字符串)并返回一个浮点数。

  • 如果 parseFloat 在解析过程中遇到了正号(+)、负号(- U+002D HYPHEN-MINUS)、数字(0-9)、小数点(.)、或者科学记数法中的指数(e 或 E)以外的字符,则它会忽略该字符以及之后的所有字符,返回当前已经解析到的浮点数。
  • 第二个小数点的出现也会使解析停止(在这之前的字符都会被解析)。
  • 参数首位和末位的空白符会被忽略。
  • 如果参数字符串的第一个字符不能被解析成为数字,则 parseFloat 返回 NaN。
  • parseFloat 也可以解析并返回 Infinity。
  • parseFloat解析 BigInt 为 Numbers, 丢失精度。因为末位 n 字符被丢弃。
1
// 以下的栗子全部返回3.14
2
parseFloat(3.14);
3
parseFloat('3.14');
4
parseFloat('  3.14  ');
5
parseFloat('314e-2');
6
parseFloat('0.0314E+2');
7
parseFloat('3.14some non-digit characters');
8
parseFloat({ toString: function() { return "3.14" } });

8. 其他类型转换为数值类型

有三个函数可以将非数值转为数值类型: Number() parseInt() parseFloat()
这三个函数对于同样的输入会返回不同的类型

方法1 Number()

转换规则上面已说过

Number('1') // 1
Number('1.123') // 1.123
Number('1.abc') // NaN
Number('')    // 0
Number(true)  // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN
Number({a:1})  // NaN

方法2 parseInt()

parseInt() 主要是将字符串转为整数
它会从第一个字符开始,直到不是数字结束

parseInt('1') //1
parseInt('1.23') // 1
parseInt('  123') // 123
parseInt('1234abc')  // 1234
parseInt('abc') // NaN
parseInt('a567bc') // NaN
parseInt(true) // NaN
parseInt(null) // NaN
parseInt(undefined) // NaN
parseInt({a:1}) // NaN
parseInt([1,2,3]) // 1

方法3 parseFloat()

parseFloat() 主要是将字符串转为浮点数

parseFloat('3.14') // 3.14
parseFloat('314e-2') // 3.14
parseFloat('0.0314E+2') // 3.14
// 其他与parseInt()结果相同

方法4 - 0

'1' - 0 // 1
'1.23' - 0  // 1.23
'1.abc' -0 // NaN
'' - 0  // 0
true -0 // 1
false - 0  // 0
null - 0 // 0
undefined - 0 // NaN
({a:1}) - 0

方法5 取正

+ '1' // 1
+ '1.23' // 1.23
+ '1.abc' // NaN
+ '' // 0
+ true // 1
+ false // 0
+ null // 0
+ undefined // NaN
+ {a:1} // NaN

9. 补充一个比较运算符的坑

不同类型

比较不同类型的数据也许会出现不可预料的结果。
如果将字符串与数字进行比较,那么在做比较时 JavaScript 会把字符串转换为数值。
空字符串将被转换为 0 非数值字符串将被转换为始终为 false 的 NaN。

1
' ' >= 0 && ' ' <= 9  // true 因为空字符串会转为0 
2
'a' >= 0 || 'a' <= 9  // false  'a' 转为数值 NaN
3
'123a' >= '123'       // false '123a'也会转为NaN

相同类型都为字符串

字符串大小会按照字母排序

1
'2' > '12'   // true
2
'2020-6-8' > '2020-6-14'  // true 因为 '8' > '14' 
3
// 所以时间格式比较日期格式要yyyy-MM-dd去比较
4
'2020-06-08' > '2020-06-14' // false  '08' < '14'