(JS基础)Number 类型

栏目: JavaScript · 发布时间: 5年前

内容简介:对于数字,我们再熟悉不过了。通过通过通过

对于数字,我们再熟悉不过了。通过 let num = 123; 可以创建一个数字。

通过 Number(thing) 可以将任何类型的数据 转化成数字

通过 new Number(thing) 可以将任何类型的数据 转化成 Number 类型的对象

数字直接量能直接使用 Number 对象上的属性和方法,如 100['toFixed'](1) 。其实语言内部会临时将 100 封装成对象,再执行相应的方法。可以看成是 Number(100).toFixed(1)

数字直接量也能用点运算( . )使用 Number 对象上的属性和方法,但是数字后要加上空格,如 100 .toFixed(1) ,因为编译器不了解 . 表示小数点还是运算符,必须加上空格表示 . 前面是一个完整的数字。

除了常见的数字外, NaN Infinity 也属于 Number 类型 。除了十进制,JavaScript 还支持二进制( 0b111 )、八进制( 0o777 ,0开头也能表示八进制,但不推荐)、十六进制( 0xfff )的数字表示方式,还有科学计数法( 2.345e+3 )表示方式。

静态属性

这些静态属性很少会用到,一般用于检测是否超过精度。(提及精度问题)

  • EPSILON:两个可表示(representable)数之间的最小间隔。2 -52
  • MAX_SAFE_INTEGER:最大的安全整数。2 -53 -1。
  • MIN_SAFE_INTEGER:最小的安全整数。-2 -53 -1。
  • MAX_VALUE:能表示的最大正数。2 1023 *[(2 53 -1)/2 52 ]。
  • MIN_VALUE:能表示的最小正数即最接近 0 的正数。2 -1022 *(1/2 52 )=2 -1074
  • NaN:特殊的“非数字”值。
  • POSITIVE_INFINITY:特殊的正无穷大值,在溢出时返回改值。溢出的正数均为该值。
  • NEGATIVE_INFINITY:特殊的负无穷大值,在溢出时返回该值。溢出的负数均为该值。

需要单独说一下,安全整数指的是能做正确运算的整数。在整数相加时,需要将指数位换算成相同的值,如 2 52 +1 = 2 52 +2 52 *2 -52 ,然后对分数位加减运算。当超出安全范围时,如2 53 +1 ,发现 1 无法转化成 2 53 *2 -53 ,因为分数位的位数只有 52 位。

(其实 Number.MAX_SAFE_INTEGER + 1Number.MIN_SAFE_INTEGER - 1 是可以得到正确的结果)

静态方法

第一个和最后两个方法比较常用。其中 Number.isNaN(value) 是比较实用的,因为我们无法通过 value===NaN 判断 value 是否为 NaN

  • isNaN(value)判断 value 是否为 NaN
  • isFinite(value):判断 value 是否为有限数,非数字类型返回 false
  • isInteger(value):判断 value 是否为整数,非数字类型返回 false
  • isSafeInteger(value):判断 value 是否为安全整数( -(2 53 - 1) 至 2 53 - 1 之间 )。
  • parseFloat(string) :把一个字符串 解析成浮点数 。传入数值会返回原值;非字符串和数字会返回 NaN ;其他情况请查看文档。
  • parseInt(string[, radix]) :根据给定的进制数把一个字符串 解析成整数radix 默认为 10 ,即十进制。传入非字符串和数字会返回 NaN ;其他情况请查看文档。

实例方法

  • toExponential(fractionDigits?):返回一个 用幂的形式(科学记数法)来表示 Number 对象的字符串fractionDigits 默认为小数点后的将尽可能用最多的位数来表示该数值。例子: 100 .toExponential();  // "1e+2"2.345 .toExponential(2);  // "2.35e+0"
  • toFixed(digits?) :返回所给数值的定点数表示法的字符串形式,即 保留 digits 位小数digits 默认为 0 。一般用于减少小数点的经度,例如 2.345 .toFixed(2);  // "2.35"
  • toLocale​String([locales [, options]]) :返回这个数字在特定语言环境下的表示字符串。
  • toPrecision(precision?) :返回 以定点表示法或指数表示法表示 的一个数值对象的字符串。 precision 表示有效数个数的整数,省略则返回原数值。例子: 100 .toPrecision(2); // "1.0e+2"2.345 .toPrecision(3); // "2.35"
  • toString(radix?):返回指定 Number 对象的字符串表示形式。radix表示转换的基数(从2到36),默认为 10 。
  • valueOf():返回一个被 Number 对象包装的原始值。

Math 对象

与其它全局对象不同的是, Math 不是一个构造器。 Math 所有属性和方法都是 静态的 。你用到的常数 pi 可以用 Math.PI 表示,用 x 作参数 Math.sin(x) 调用 sin 函数。JavaScript 中的常数,是以全精度的实数定义的。

属性

一般用于得到 数学常量

  • E: 欧拉常数 ,也是自然对数的底数,约等于 2.718 。
  • LN2: 2 的自然对数 ,约等于 0.693 。
  • LN10: 10 的自然对数 ,约等于 2.303 。
  • LOG2E: 以 2 为底 E 的对数 ,约等于 1.443 。
  • LOG10E: 以 10 为底 E 的对数 ,约等于 0.434 。
  • PI: 圆周率 ,约等于 3.14159 。
  • SQRT1_2: 1/2 的平方根 ,约等于 0.707 。
  • SQRT2: 2 的平方根 ,约等于 1.414 。

方法

普通运算

  • abs(x):返回 x 的 绝对值
  • sign(x):返回 x 的 符号 函数,5 种可能返回的值:参数是±0,返回原值;其他正数返回 1 ;其他负数返回 -1 ;其他参数返回 NaN
  • ceil(x): 返回 x 向上取整 后的值。
  • floor(x):返回 x 向下取整 后的值。
  • round(x):返回 四舍五入 后的整数。
  • trunc(x):返回 x 的 整数部分 ,去除小数。
  • random():返回 0 到 1 之间的伪随机数

开方

  • sqrt(x): 返回 x 的 平方根
  • hypot(...[x1,x2,...]?):返回它的 所有参数的平方和的平方根
  • cbrt(x): 返回 x 的 立方根

幂运算

  • exp(x):返回 E x ,E 为欧拉常数。
  • expm1(x):返回 exp(x) - 1 的值。
  • pow(x,y):返回 x 的 y 次幂 。这里还有另一种写法,使用**运算符,即 x**y

对数运算

  • log(x):返回 x 的自然对数。 log e X , 即 lnX 。
  • log1p(x):返回 x+1 的自然对数,等效于 Math.log(x+1)
  • log10(x):返回以 10 为底数的 x 的对数。 log 10 X ,即 lgX 。
  • log2(x):返回以 2 为底数的 x 的对数。 log 2 X

三角函数

  • sin(x):返回 x 的 正弦 值。
  • cos(x): 返回 x 的 余弦 值。
  • tan(x): 返回 x 的 正切 值。
  • asin(x):返回 x 的反正弦值。
  • acos(x):返回 x 的反余弦值。
  • atan(x):以介于 -PI/2 与 PI/2 弧度之间的数值来返回 x 的反正切值。
  • sinh(x):返回 x 的双曲正弦值。
  • cosh(x):返回 x 的双曲余弦值。
  • tanh(x):返回 x 的双曲正切值。
  • asinh(x): 返回 x 的反双曲正弦值。
  • acosh(x):返回 x 的反双曲余弦值。
  • atanh(x): 返回 x 的反双曲正切值。
  • atan2(y, x):返回 y/x 的反正切值。

求最值

  • max (...[x1,x2,…]?):返回所有参数中的 最大值
  • min (...[x1,x2,…]?):返回所有参数中的 最小值

精度

  • clz32(x):返回 x 转化成32位无符号整形的数的二进制的前导零的数量。
  • fround(x): 返回数字 x 的最接近的单精度浮点型表示。
  • imul(x1, x2):两个参数的类C的32位整数乘法运算的运算结果。(这个的转化过程我也没搞懂,有大神路过可以帮我解惑)

精度问题

0.1+0.2!==0.3

关于精度问题,从一个简单的加法开始。

console.log(0.1 + 0.2);   // 0.30000000000000004复制代码

这是由于 JavaScript 采用 IEEE 754 标准,所以上述问题并非 JavaScript 特有,是使用该标准的的编程语言都存在的问题。下面简单讲解问题发生的原因。(相关专业知识请查阅书本或文档)

浮点数的组成

IEEE 754 规定了包括:单精度(32位)、双精度(64位)、延伸单精度(43比特以上,很少使用)与延伸双精度(79比特以上,通常以80位实现)。而 JavaScript 使用的是双精度

一个浮点数(value)可以这样表示:

(JS基础)Number 类型

一个浮点数的存储方式如下图:

(JS基础)Number 类型

总共分为三部分:

  1. 符号位 (sign),只占 1 位,0 表示 + ,1 表示 -
  2. 指数位 (exponent),单精度占 8 位;双精度占 11 位。要注意的是,这部分表示的是 2 的指数 。指数位的值为真实的指数值加上 指数偏移值 。例如对于单精度,指数位存储 2 ,需要加上2 7 -1,即 131 ,用二进制表示为 1000 0011 。下面介绍指数位的范围。
  3. 分数位 (fraction),占余下的的位。下面介绍二进制分数位的转换。

规约形式的浮点数

如果浮点数中指数部分的编码值在 0<exponent≤2 e -2 之间,且在科学表示法的表示方式下, 分数 (fraction) 部分最高有效位(即整数字)是 1 (并不会存储) ,那么这个浮点数将被称为 规约形式的浮点数 。简单说就是, 指数部分 用二进制为 000...001111...110 之间; 分数部分 的实际值大于等于 0.5 ,小于 1 。关于换算,下面会说。

非规约形式的浮点数

如果浮点数的指数部分的编码值是 0 ,即实际指数值为 -126 ;分数部分非零,那么这个浮点数将被称为非规约形式的浮点数。 IEEE 754标准规定: 非规约形式的浮点数的指数偏移值比规约形式的浮点数的指数偏移值小 1 ,即 2 e-1 -2 。主要是用于解决填补绝对值意义下最小规格数与零的距离。

指数偏移值

(下面用 e 表示指数位的位数)

对于 规约形式的浮点数 ,指数偏移值为 2 e-1 -1 。由于该值 不能为 0 ,所以实际的指数范围为 -126 到 127

对于 非规约形式的浮点数 ,指数偏移值为 2 e-1 -2 ,即比规约形式的浮点数的偏移值要小 1 。由于该值 只能为 0 ,所以实际的指数值为 -126

总的来说就是,实际的指数值范围为 -126 到 127 。 000...001 是规约形式的浮点数的指数位的最小值; 000...000 是非规约形式的浮点数的指数位的最小值,两者表示的实际指数值都是

-126 。

特殊值

这里有三个特殊值需要指出:

如果 指数 是 0 并且尾数的 小数部分 是 0 ,这个数 ±0(和符号位相关)

如果 指数 = 2 e-1 -1 并且尾数的 小数部分 是 0 ,这个数是 ±∞(同样和符号位相关)

如果 指数 = 2 e-1 -1 并且尾数的 小数部分 非 0 ,这个数表示为不是一个数(NaN)。

分数位的转换

要明确的是, 分数位的十进制值必须是大于 1 小于 2 的数 。下面以 1.625 为例。

我们并不能直接看成 1625 转成二进制。需要使用如下方法(用 f 表示当前十进制数值):

第一步先把数值减 1 得到新的数值,第一位取 1 。新的数值 *2 ,若整数部分得到 1 ,则该位为 1 ,否则为 0 ;然后继续取小数部分同上操作,得到后面位的值,直到数刚好为 0 或达到规定位数的最大值(最大精度)。

举个实际例子,对于 1.625

1.625
0.625 * 2 = 1.250
0.25* 2 = 0.5
0.5 * 2 = 1.0

后面用 0 补全位数即可。

所以, 在二进制,第一个有效数字必定是 1 ,因此这个 1 并不会存储

(如何从二进制的值得到十进制?对于上面的例子是: "1101"/2 3 =13/8=1.625 )

格式化浮点数

对于那些大于 1 或小于 0.5 的浮点数来说,需要格式化后才能看出"三部分"分别的值是多少。(因为要保证二进制的分数位的实际第一位是 1 )简单说就是要 使得 1≤fraction<2

6.625 为例,需要换算成 1.65625 * 2 2 。然后我们用上面的方法,把 1.65625 换算成二进制就是 110101 00...

但是,最高位的 1 并不会存储,所以得到的 分数位 的二进制值为 10101 00... (尾数用 0 补全)。

指数 位为 3 ,加上偏移值得到的二进制值为 100...011 (中间都是 0)。

上面演示了 fraction≥2 的情况,就是乘以 2 n (n>0);而 fraction<1 也一样乘以 2 n ,不同的是 n<0 。

更直观的换算方法

同样以 6.625 为例:

  1. 把小数点前后 分成两部 分看,分别是 60.625
  2. 我们对 整数部分 6 的进制转换比较熟悉,结果是 110
  3. 小数点后的部分 0.625 按照类似于上面的分数位的转换规则,但忽略第一步,得到的结果是 101
  4. 两者组合起来就是 110.101
  5. 转换成 1.xxxx 的形式,即 1.10101 ,最高位省略,得 分数位10101
  6. 对比于原值 110.101 的小数点向前左移动了 2 位,则得到 指数位 的值为 2 ,加上指数偏移值得到 100...001 (省略的是0)。
  7. 最后组合成 0 100...001 101010... (省略的是 0 )。

而对于 0.2 这种小于 1 的数,也是类似的做法,区别在于第 6 步,"向左移动"变为"向右移动",得到的指数位的值为负数,即 -3 ,加上指数偏移值得到的是 011...100 (省略的是1)。

回到问题本身

所以对于 0.1 和 0.2 来说,根据上main的方法得到的二进制的值都是 11001100... ,都是以 1100 不断重复。

计算机存储的位数是有限的,必须把超出的位数舍去。所以对于这种,在有限精度内不能完全表示的,就会造成精度缺失。就是 11001100... 从二进制转换回十进制后总会比原来的值小那么一点。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The NSHipster Fake Book (Objective-C)

The NSHipster Fake Book (Objective-C)

Mattt Thompson / NSHipster Portland, Oregon / 2014 / USD 19.00

Fake Books are an indispensable tool for jazz musicians. They contain the melody, rhythm, and chord changes for hundreds of standards, allowing a player to jump into any session cold, and "fake it" th......一起来看看 《The NSHipster Fake Book (Objective-C)》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试