数字类型概述
JavaScript使用64位浮点数格式表示所有数字:
- 整数和浮点数 - 没有单独的整数类型
- 特殊数值 - Infinity, -Infinity, NaN
- 数值范围 - 有限的表示范围
- 精度问题 - 浮点数运算的精度限制
- BigInt类型 - ES2020引入的大整数类型
- 数值分隔符 - ES2021引入的可读性改进
数字表示
数字表示方式
// 十进制整数
let decimal = 42;
// 浮点数
let float = 3.14159;
let scientific = 1.23e6; // 1230000
// 二进制 (ES6)
let binary = 0b1010; // 10
// 八进制 (ES6)
let octal = 0o755; // 493
// 十六进制
let hex = 0xFF; // 255
// 大数字可读性 (ES2021)
let bigNumber = 1_000_000_000; // 1000000000
console.log(binary, octal, hex, bigNumber);
特殊数值
特殊数值
// Infinity 和 -Infinity
console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(Number.MAX_VALUE * 2); // Infinity
// NaN (Not a Number)
console.log(0 / 0); // NaN
console.log("hello" * 5); // NaN
console.log(Math.sqrt(-1)); // NaN
// 检查特殊值
console.log(isNaN(NaN)); // true
console.log(isNaN("hello")); // true (会先尝试转换为数字)
console.log(Number.isNaN(NaN)); // true (ES6, 不会类型转换)
console.log(Number.isNaN("hello")); // false
console.log(isFinite(42)); // true
console.log(isFinite(Infinity)); // false
console.log(Number.isFinite(42)); // true (ES6)
数值范围和精度
数值范围和精度
// 数值范围
console.log(Number.MAX_VALUE); // 1.7976931348623157e+308
console.log(Number.MIN_VALUE); // 5e-324
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
// 精度问题
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
// 解决精度问题
function areEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(areEqual(0.1 + 0.2, 0.3)); // true
// 安全整数检查
console.log(Number.isSafeInteger(42)); // true
console.log(Number.isSafeInteger(9007199254740992)); // false
数字转换
数字转换
// 显式转换
console.log(Number("42")); // 42
console.log(Number("42px")); // NaN
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
// parseInt 和 parseFloat
console.log(parseInt("42")); // 42
console.log(parseInt("42px")); // 42 (忽略非数字部分)
console.log(parseInt("1010", 2)); // 10 (二进制解析)
console.log(parseFloat("3.14")); // 3.14
console.log(parseFloat("3.14.15")); // 3.14 (遇到第二个小数点停止)
// 一元加运算符
console.log(+"42"); // 42
console.log(+true); // 1
console.log(+""); // 0
// 隐式转换
console.log("5" - 3); // 2
console.log("5" * "2"); // 10
console.log("5" / "2"); // 2.5
Math对象 - 基本数学运算
| 方法 | 描述 | 示例 | 结果 |
|---|---|---|---|
Math.abs(x) |
绝对值 | Math.abs(-5) |
5 |
Math.sqrt(x) |
平方根 | Math.sqrt(16) |
4 |
Math.pow(x, y) |
x的y次幂 | Math.pow(2, 3) |
8 |
Math.exp(x) |
e的x次幂 | Math.exp(1) |
~2.718 |
Math.log(x) |
自然对数 | Math.log(10) |
~2.302 |
基本数学运算示例
// 基本运算
console.log(Math.abs(-5)); // 5
console.log(Math.sqrt(16)); // 4
console.log(Math.pow(2, 8)); // 256
console.log(Math.exp(1)); // ~2.718
console.log(Math.log(Math.E)); // 1
// 使用指数运算符 ** (ES2016)
console.log(2 ** 8); // 256
console.log(Math.sqrt(16) === 16 ** 0.5); // true
// 对数运算
console.log(Math.log10(100)); // 2
console.log(Math.log2(8)); // 3
Math对象 - 舍入和取整
| 方法 | 描述 | 示例 | 结果 |
|---|---|---|---|
Math.round(x) |
四舍五入 | Math.round(4.7) |
5 |
Math.ceil(x) |
向上取整 | Math.ceil(4.2) |
5 |
Math.floor(x) |
向下取整 | Math.floor(4.7) |
4 |
Math.trunc(x) |
去除小数部分 | Math.trunc(4.7) |
4 |
Math.fround(x) |
最接近的单精度浮点数 | Math.fround(1.337) |
1.3370000123977661 |
舍入和取整示例
// 各种舍入方法
console.log(Math.round(4.7)); // 5
console.log(Math.round(4.4)); // 4
console.log(Math.round(-4.7)); // -5
console.log(Math.ceil(4.2)); // 5
console.log(Math.ceil(-4.2)); // -4
console.log(Math.floor(4.7)); // 4
console.log(Math.floor(-4.7)); // -5
console.log(Math.trunc(4.7)); // 4
console.log(Math.trunc(-4.7)); // -4
// 自定义舍入函数
function roundTo(number, precision) {
let factor = Math.pow(10, precision);
return Math.round(number * factor) / factor;
}
console.log(roundTo(3.14159, 2)); // 3.14
console.log(roundTo(1.005, 2)); // 1.01
Math对象 - 三角函数
三角函数示例
// 角度与弧度转换
function toRadians(degrees) {
return degrees * (Math.PI / 180);
}
function toDegrees(radians) {
return radians * (180 / Math.PI);
}
// 三角函数 (使用弧度)
let angle = toRadians(45);
console.log(Math.sin(angle)); // ~0.707
console.log(Math.cos(angle)); // ~0.707
console.log(Math.tan(angle)); // ~1
// 反三角函数 (返回弧度)
console.log(toDegrees(Math.asin(0.5))); // 30
console.log(toDegrees(Math.acos(0.5))); // 60
console.log(toDegrees(Math.atan(1))); // 45
// 双曲函数
console.log(Math.sinh(1)); // ~1.175
console.log(Math.cosh(1)); // ~1.543
console.log(Math.tanh(1)); // ~0.762
Math对象 - 随机数和极值
随机数和极值
// 随机数
console.log(Math.random()); // 0到1之间的随机数
// 生成指定范围的随机整数
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(randomInt(1, 10)); // 1到10之间的随机整数
// 极值函数
console.log(Math.max(1, 5, 3, 9, 2)); // 9
console.log(Math.min(1, 5, 3, 9, 2)); // 1
// 使用扩展运算符处理数组
let numbers = [1, 5, 3, 9, 2];
console.log(Math.max(...numbers)); // 9
console.log(Math.min(...numbers)); // 1
// 符号函数
console.log(Math.sign(5)); // 1
console.log(Math.sign(-5)); // -1
console.log(Math.sign(0)); // 0
console.log(Math.sign(-0)); // -0
数值计算和精度处理
处理浮点数精度问题的实用方法:
精度处理函数
// 精确加法
function preciseAdd(a, b) {
let factor = Math.pow(10, Math.max(getDecimalLength(a), getDecimalLength(b)));
return (Math.round(a * factor) + Math.round(b * factor)) / factor;
}
// 精确乘法
function preciseMultiply(a, b) {
let factor = Math.pow(10, getDecimalLength(a) + getDecimalLength(b));
return (Math.round(a * factor) * Math.round(b * factor)) / (factor * factor);
}
// 获取小数位数
function getDecimalLength(num) {
const str = num.toString();
const decimalIndex = str.indexOf('.');
return decimalIndex === -1 ? 0 : str.length - decimalIndex - 1;
}
// 使用示例
console.log(preciseAdd(0.1, 0.2)); // 0.3
console.log(preciseMultiply(0.1, 0.2)); // 0.02
数值格式化和本地化
使用Intl API进行数值格式化和本地化:
数值格式化
// 货币格式化
let amount = 1234567.89;
let formatter = new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: 'CNY'
});
console.log(formatter.format(amount)); // "¥1,234,567.89"
// 百分比格式化
let percentFormatter = new Intl.NumberFormat('zh-CN', {
style: 'percent',
minimumFractionDigits: 2
});
console.log(percentFormatter.format(0.123)); // "12.30%"
// 单位格式化
let unitFormatter = new Intl.NumberFormat('zh-CN', {
style: 'unit',
unit: 'meter',
unitDisplay: 'long'
});
console.log(unitFormatter.format(1000)); // "1,000米"
// 不同地区的数字格式
console.log(new Intl.NumberFormat('en-US').format(1234567.89)); // "1,234,567.89"
console.log(new Intl.NumberFormat('de-DE').format(1234567.89)); // "1.234.567,89"
BigInt (ES2020)
BigInt用于表示任意精度的整数:
BigInt示例
// BigInt 创建
let big1 = 123n;
let big2 = BigInt(456);
let big3 = BigInt("789");
console.log(big1, big2, big3);
// 超出安全整数范围
console.log(9007199254740991 + 1); // 9007199254740992 (正确)
console.log(9007199254740991 + 2); // 9007199254740992 (错误!)
console.log(9007199254740991n + 1n); // 9007199254740992n
console.log(9007199254740991n + 2n); // 9007199254740993n (正确)
// 运算
console.log(10n + 20n); // 30n
console.log(10n * 20n); // 200n
console.log(10n ** 3n); // 1000n
// 除法 (BigInt除法会截断小数部分)
console.log(7n / 2n); // 3n (不是3.5n)
// 不能与普通数字混合运算
// console.log(10n + 5); // 错误
console.log(10n + BigInt(5)); // 15n
// 比较运算可以混合使用
console.log(10n == 10); // true
console.log(10n === 10); // false (类型不同)
数值算法和实用函数
常用的数值算法和实用函数:
实用数值函数
// 生成斐波那契数列
function fibonacci(n) {
if (n <= 1) return n;
let a = 0, b = 1;
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b];
}
return b;
}
// 计算阶乘
function factorial(n) {
if (n <= 1) return 1;
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
}
// 计算最大公约数
function gcd(a, b) {
while (b !== 0) {
[a, b] = [b, a % b];
}
return a;
}
// 计算最小公倍数
function lcm(a, b) {
return (Math.abs(a * b)) / gcd(a, b);
}
// 使用示例
console.log(fibonacci(10)); // 55
console.log(factorial(5)); // 120
console.log(gcd(48, 18)); // 6
console.log(lcm(12, 18)); // 36
实践练习
练习代码
// 练习1: 生成随机颜色
function randomColor() {
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
return `rgb(${r}, ${g}, ${b})`;
}
console.log(randomColor());
// 练习2: 计算两点之间的距离
function distance(x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}
console.log(distance(0, 0, 3, 4)); // 5
// 练习3: 金融计算 - 货币格式化
function formatCurrency(amount) {
return '¥' + amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
console.log(formatCurrency(1234567.89)); // "¥1,234,567.89"
// 练习4: 质数检测
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 === 0 || n % 3 === 0) return false;
for (let i = 5; i * i <= n; i += 6) {
if (n % i === 0 || n % (i + 2) === 0) return false;
}
return true;
}
console.log(isPrime(17)); // true
console.log(isPrime(18)); // false
最佳实践
- 使用
Number.isNaN()而不是isNaN()检查NaN - 处理货币时使用整数(分)而不是浮点数(元)
- 使用
Math.floor()而不是parseInt()进行取整 - 对于大整数,使用BigInt而不是普通数字
- 比较浮点数时使用容差而不是严格相等
- 使用
Number.EPSILON作为默认容差 - 使用
Intl.NumberFormat进行本地化数字格式化 - 避免在循环中创建新的Math函数对象