专题 数字(Number)基础
你将知道:
- 整数和浮点数
- 数字原语和
Number
对象 - Flooring 和 ceiling
- 科学记数法和符号
e
- 转换为数字
- 特殊数字
NaN
和Infinity
- 检查特殊数字 —
isNaN()
和isFinite()
整数和浮点数
数字通常分为两类: 整数和浮点数 。
整数是整数,其中没有小数点。
例如 0、1、2、3 等。整数也可以是负数,例如 -1、-2、-3 等。这没什么好说的
var num = 10;// 创建了一个num, 或者说声明了一个变量num ,并给他分配一个整数值10,或者说赋值给这个变量10
浮点数 ,或简称为浮点数 ,是带有小数点的数字。
例如 1.5、2.3、7.2。与整数一样,浮点数也可以进入负值范围,例如 -1.5、-50.123、-1000.009 等。
var num = 10.5;
在我们继续之前,澄清一件事非常重要。
JavaScript 将所有数字(无论是整数还是浮点数)都归为一种类型,即数字 。换句话说,-1、-1.5、-2、-0.005、0、1000、105.855 在 JavaScript 中都只是数字。咱们之前提到过。
- 即使在 Javascript 内部,所有的数字也以相同的方式存储。即 使用 这里得记住了: IEEE-754 双精度浮点格式。
这说明什么?
说明 Javascript 中 所有的数字 在内部都是以浮点数的格式存储,对整数也是,那么这在进行整数运算的时候可能导致一些意想不到的后果。 面试常问。
现在,下次您在 JavaScript 中看到整数(例如 10
时,)您就会知道它在内部不是表示为整数,而是表示为浮点数。
数字原语和对象
我们之前了解了 JavaScript 语言中的原语和对象。在讨论等效的对象类型之前,让我们先快速回顾一下数字原语 -> 你就想数字 10。
原语是没有附加任何属性/方法的值。 10 能有啥属性方法?
在 JavaScript 中,有 5 种主要原始类型:数字、字符串、布尔值、 undefined
和 null
,Symbol 跟 bigInt 后续再说,毕竟使用频率不是没前几个高。
那么:
使用数字文字创建数字原语 。
回想一下,字面量是源代码中值的精确表示。在 JavaScript 中,数字只能以字面量表示。
数字文字创建数字原语 。不附带任何属性方法。
var x = 50.5
这里我们创建了一个变量 x
,并将一个数字字面量 50.5
赋值给它。这个字面量创建了一个数字原语。所以 x
保存的是一个数字原语;它没有附加任何属性/方法。
要检查给定的原始值是否为数字,我们可以使用 typeof
运算符。 返回是 'number'
typeof 10
'number'
typeof 0.0004
'number'
typeof -33
'number'
在 JavaScript 中,除了数字原语之外,我们还可以创建数字对象 。
要创建数字对象,我们使用 Number()
函数,并使用 new
关键字调用它。使用 new
调用时,函数被称为构造函数 。
我们将在 JavaScript 对象 - 构造函数一章中探讨有关构造函数的所有细节。
new Number([value]);
让我们创建几个数字对象。当不传入任何参数时, new Number()
会创建一个 Number
对象,其等效原始值为 0
。如以下代码所示:
var num = new Number();
console.log(num);
让我们看看当使用 typeof
检查数字对象时返回什么:
var num = new Number();
console.log(typeof num); 'object'
可以看出, typeof
对数字对象返回 'object'
。与此相反,正如我们从上面的讨论中记得的那样,它对数字原语返回 'number'
。要为其他数字创建对象,我们将该数字作为参数传递给 Number()
构造函数。
var num = new Number(10);
console.log(num); // Number {10}
在这里,我们在原始数字 10
上创建了一个数字对象 num
。
数字对象也是数字,因此也可以用于算术运算。但是,这些运算的返回值是一个数字原语, 而不是一个对象。
new Number(10) + new Number(20)
>>> 30
不过,在 JavaScript 程序中使用 new Number()
来创建数字是毫无意义的 。
Number()
构造函数的用途
JavaScript 中有一些方法可以对给定的数字进行调用。例如,我们来考虑一下 toString()
方法。(下一章将具体细说)。
当调用数字时, toString()
会将其转换为等效的字符串表示形式。注意,实际的数字并没有改变——它会复制该数字,然后将复制的数字转换为字符串。
var num = 10;
num.toString()
'10'
现在你看到这段代码可能会一愣。 为什么这么说呢?
因为我们正在访问 num
上的方法,它是一个原语;并且我们知道原语没有附加的属性/方法。访问原始类型的属性/方法与我们迄今为止所获得的知识相冲突,因为原始类型上没有可用的方法。
实际上,数字原语 num
实际上没有任何属性和方法!indeed。上面的代码看起来好像访问了原始类型 num
的一个方法,但在幕后,情况却大不相同 。让我们深入探究一下……
当 JavaScript 解释器发现某个原语上的属性/方法正在被访问时,它会将该原语装入一个对象中,并对该对象执行属性访问。
三种原始类型(数字、字符串和布尔值)中的每一个都有一个相应的函数,可以在构造函数的上下文中调用该函数来为该原始类型创建一个对象。
对于数字来说,正如我们刚才看到的,这个函数是 Number()
。当在构造函数的上下文中调用它时,即使用 new
关键字,它返回一个 Number
类型的对象。
上面的代码会自动翻译成如下内容:
var num = 10;
var _num = new Number(num); // Done automatically by JavaScript
console.log(_num.toString());_num = null;
自动装箱啦,还记得不 😇
注意这里的虚数标识符 _num
。每次访问原始值 num
,都会被替换为这个值 _num
。这样一来,看起来好像 toString()
是直接在原始值 num
上访问的,但事实并非如此——而是在包装器数字对象 _num
上访问的。最后,通过将 _num
设置为 null
,从内存中删除此包装对象。
上面的代码只是为了让你了解当通过原始值访问属性时 JavaScript 引擎内部发生了什么。它并不是 JavaScript 内部的精确描述,JavaScript 内部可能包含许多繁琐的细节来处理此类语句!
因此,归根结底,这是 new Number()
以及其余包装类型的唯一用途——当原始类型用作对象时对其进行装箱 。
Flooring and ceiling 翻译过来地板 和 天花板
介绍 floor 和 ceil 函数
floor 函数表示为 f(x)=⌊x⌋。给定一个数字 x,它返回小于或等于 x 的最大整数。例如, ⌊10.999⌋ 返回 10。
ceil 函数表示为f (x )=⌈x ⌉ 。给定一个数字 x ,它返回大于或等于 x 的最小整数。例如, ⌈10.001⌉返回 11。
在 JavaScript 中,这些函数分别作为全局 Math
对象上的方法 floor()
和 ceil()
使用。
Math.floor( x )
接受参数 x
并返回其下限,而 Math.ceil( x )
接受参数 x
并返回其上限。
example:
Math.floor(10.5) >>> 10
Math.floor(10) >>> 10
Math.floor(10.9999) >>> 10
Math.floor(-5.6) >>> -6
Math.floor(-5.1) >>> -6
Math.floor(-5) >>> -5
Math.ceil(10.5) >>> 11
Math.ceil(10) >>> 10
Math.ceil(10.0005) >>> 10
Math.ceil(-5.6) >>> -5
Math.ceil(-5.1) >>> -5
Math.ceil(-5) >>> -5
在 JavaScript 中,当您实现许多常用算法时,您会发现自己经常使用 Math.floor()
和 Math.ceil()
方法。
科学记数法
当表示包含大量数字的巨大数字或微小数字时,将其简化为科学计数法会很方便。
科学计数法 ,也称为标准形式 、 标准符号和 E 符号 (在数字设备上),是指数字以如下所示的形式表示,
m × 10n
其中 m 是尾数 , 10 是底数 , n 是指数 。科学记数法在数学和科学计算中经常使用,用来表示极小或极大的数字。
例如,数字 0.000000000000003756可以表示为 3.756×10−15,其中 3.7563.756 是尾数, −15 是指数。同样,数字 20210000000000000000000000 可以简洁地表示为2.021×1025 。
在这两个例子中,可以看出,与用普通十进制表示的数字相比,用科学计数法表示的数字更容易读写。回到 JavaScript,符号 e
用于表示科学计数法中的数字。
<mantissa>and<exponent>1e3 >>> 100 就是1 * 10的3次方
3.254e2 >>> 325.4
100e2 >>> 10000
请记住,JavaScript 数字基于 IEEE-754 格式,因此该语言中可以表示的最大数字大约小于 1.8e308
。创建一个大于此最大限制(甚至等于它)的数字将导致它被特殊值 Infinity
替换(下面将详细介绍),如下所示:
5e1000 >>> Infinity
事实上,可以通过 Number.MAX_VALUE
属性精确访问这个最大值。
Number.MAX_VALUE
属性
Number
对象上的 MAX_VALUE
属性表示基于 IEEE-754 浮点格式的 JavaScript 中可存储的最大数字。
Number.MAX_VALUE >>> 1.7976931348623157e+308
转换为数字
JavaScript 为开发者提供了多种将给定值转换为数字的方法。下面,我们将逐一介绍这些方法。
1. Number()
此函数用于将给定值转换为数字。
在开始之前,请注意一点: Number()
函数与 Number()
构造函数不同。是的,它们都使用相同的函数,但前者在函数上下文中调用函数并返回一个数字原语,而后者在构造函数上下文中调用函数并返回一个数字对象。 (还记得吗?)
在之前的讨论中,我们说过建议避免使用创建数字对象的 Number()
构造函数;而不是避免使用允许我们将给定值转换为等效数字表示形式的 Number()
函数(不带 new
关键字)。
Number()
函数接受一个参数并返回与给定值等价的数字。
Number([value])
值 | 数值等效 |
Number | 数字本身 |
|
|
Non-empty string 非空字符串 | Parsed 解析 |
|
|
|
|
|
|
|
|
Object | Parsed 解析 |
Number('50') >>> 50
Number('3.1415') >>> 3.1415
Number(true) >>> 1
在第一个语句中,我们将 '50'
传递给 Number()
,同样返回 50
。在第二个语句中,我们传递另一个这样的字符串,这次它包含一个浮点数,即 '3.142'
,同样返回 3.142
。
在接下来的两个语句中,我们将布尔值 true
和 false
传递给函数并获取返回的等效值 - 对于 true
返回 1
,对于 false
返回 0
。
当 Number()
的参数是值 undefined
或包含非数字字符的字符串时,该函数返回 NaN
。
NaN
是 JavaScript 中的一个特殊数字。它代表“非数字”,用于表示表达式或调用的结果没有给出有意义的数字。
NaN 中文 “不是一个数字”谢谢
Number('20a') >>> NaN
Number('a20') >>> NaN
Number('abc') >>> NaN
字符串 '20a'
的末尾包含一个非数字字符,因此 JavaScript 解释器无法理解如何将其转换为等效的数字。对于无法完全解析为数字的字符串,它通过返回 NaN
来简化工作。
2. parseInt()
有时,正如我们上面所见, Number()
无法正确地从字符串中解析出数字。例如,考虑字符串 '42px'
。 Number('42px')
返回 NaN
,因为该字符串包含非数字字符。在 JavaScript 中检索 CSS 属性的值时经常需要进行这种转换。很遗憾,正如我们所见,在这种情况下无法使用 Number()
。现在该怎么办?
好吧,我们可以使用 parseInt()
函数来解决这样的转换问题。
parseInt(string[, radix])
在内部,在 parseInt()
中, string
被强制转换为字符串,因此如果将非字符串值指定为 string
,它将被转换为字符串,然后解析为整数。
parseInt()
解析 string
的方式(强制转换为字符串之后)如下所示:
- 从字符串的开头删除空格。
- 如果结果字符串的第一个字符是
-
,则将其从字符串中删除,并且记住最终解析的数字必须带负号。 - 记下结果字符串中第一个非整数数字(包括减号(
-
)、空格字符和所有字母字符以及许多其他字符串字符)的索引。 - 如果此索引为
0
,则返回NaN
。 - 从字符串中提取一个切片,从索引
0
开始,到步骤 3 中获得的索引结束(此索引是唯一的)。 - 该切片被转换成整数。
- 如果满足步骤 2 中的条件,则整数带有负号。
- 最后返回结果整数。
简而言之, parseInt()
从字符串的起始部分解析出一个整数。
parseInt('50') >>> 50
parseInt('50px') >>> 50
parseInt('a50') >>> NaN
parseInt('-50') >>> -50
parseInt(' 20') >>> 20
parseInt('50.5') >>> 50
3. parseFloat()
parseFloat()
函数的行为与 parseInt()
类似,只是它从给定的参数中解析出浮点数。
如果你还记得一件事,JavaScript 中的所有数字在内部都存储为浮点数。这意味着 parseFloat()
甚至可以从给定的字符串中提取一个整数。这是因为在 JavaScript 中,偶数也是浮点数,所以从技术上讲, parseFloat()
在这种情况下也会提取一个浮点数。
parseFloat('20.5a') >>> 20.5
parseFloat('20') >>> 20
parseFloat('-100.123abc') >>> -100.123
parseFloat('a20') >>> NaN
parseFloat('abc') >>> NaN
parseInt()
或 parseFloat()
?
如果您知道要转换为数字的字符串末尾有非数字字符,那么您就知道不能使用 Number()
,而只能在 parseInt()
和 parseFloat()
之间进行选择。
现在,如果您不确定一开始的数字类型到底是什么,最好使用 parseFloat()
,因为它可以从字符串中提取整数和浮点数。
但是,如果您确实知道字符串开头总是有一个整数,那么最好使用 parseInt()
,因为它比 parseFloat()
进行的解析更少。
4. 一元加号( +
)运算符
除了上面显示的三个函数之外,还有一种更简单的方法可以将给定值转换为数字。
一元加号( +
)运算符接受一个表达式,将其转换为数字并返回该数字。
+expression
一元加运算符本质上是对给定值调用 Number()
的简写形式。其转换规则与 Number()
完全相同。
特殊号码
由于 JavaScript 中的数字基于 IEEE-754 格式,因此该语言中存在两种数字特例。一个是 NaN
,另一个是 Infinity
1. NaN
NaN
代表“非数字”,用于表示不能为数字或无法定义的数字表达式的结果。
Number('a') >>> NaN
+'20a' >>> NaN
Infinity - Infinity >>> NaN
0 / 0 >>> NaN
2. Infinity
Infinity
用于表示数学上不可能的计算结果或超过 Number.MAX_VALUE
值的表达式。
检查特殊数字
1. isNaN()
isNaN()
函数只是告诉我们给定值是否为 NaN
。
isNaN(value)
value
是一个数字或其他值,在这种情况下,它会先被强制转换为数字,然后再继续执行。
如果 value 是 NaN ,返回 true, 否则返回 false。
记住: 两个 NaN 值不相等!!!!!
2. isFinite()
isFinite()
函数告诉我们给定值是否有限。
不多说了,完事。