数字与数学运算

全面掌握JavaScript数字处理、数学运算、Math对象和数值计算

数字类型概述

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函数对象

下一步学习

掌握了数字与数学后,接下来可以学习: