Number对象与方法
Number对象与方法
JavaScript的Number对象提供了处理数值的属性和方法。本文将介绍Number对象的常量、格式化方法以及数值转换和检测方法。
Number对象概述
在JavaScript中,Number是一个原始值的包装对象,用于表示和操作数值。当作为构造函数调用时,它会创建Number对象;当不带new关键字调用时,它会将参数转换为数值。
// 创建Number对象
const numObject = new Number(42);
console.log(typeof numObject); // "object"
// 转换为数值
const num = Number("42");
console.log(typeof num); // "number"
Number常量
Number对象提供了几个有用的常量属性:
常量 | 描述 | 值 |
---|---|---|
Number.MAX_VALUE | 可表示的最大正数 | 约1.79E+308 |
Number.MIN_VALUE | 可表示的最小正数 | 约5E-324 |
Number.MAX_SAFE_INTEGER | 可安全表示的最大整数 | 9007199254740991 (2^53 - 1) |
Number.MIN_SAFE_INTEGER | 可安全表示的最小整数 | -9007199254740991 -(2^53 - 1) |
Number.POSITIVE_INFINITY | 正无穷大 | Infinity |
Number.NEGATIVE_INFINITY | 负无穷大 | -Infinity |
Number.NaN | 非数值 | NaN |
Number.EPSILON | 1与大于1的最小浮点数之间的差 | 约2.22E-16 |
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(Number.POSITIVE_INFINITY); // Infinity
console.log(Number.NEGATIVE_INFINITY); // -Infinity
console.log(Number.NaN); // NaN
console.log(Number.EPSILON); // 2.220446049250313e-16
数值检测方法
Number对象提供了几个静态方法来检测数值:
Number.isFinite()
检测一个值是否为有限数值(不是Infinity、-Infinity或NaN)。
console.log(Number.isFinite(42)); // true
console.log(Number.isFinite(Infinity)); // false
console.log(Number.isFinite(NaN)); // false
console.log(Number.isFinite("42")); // false(不进行类型转换)
// 与全局isFinite()的区别
console.log(isFinite("42")); // true(进行类型转换)
Number.isInteger()
检测一个值是否为整数。
console.log(Number.isInteger(42)); // true
console.log(Number.isInteger(42.0)); // true
console.log(Number.isInteger(42.5)); // false
console.log(Number.isInteger("42")); // false
Number.isNaN()
检测一个值是否为NaN。
console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN(Number.NaN)); // true
console.log(Number.isNaN(0 / 0)); // true
console.log(Number.isNaN("NaN")); // false(不进行类型转换)
// 与全局isNaN()的区别
console.log(isNaN("NaN")); // true(进行类型转换)
Number.isSafeInteger()
检测一个值是否为安全整数(在-(2^53 - 1)到2^53 - 1之间的整数)。
console.log(Number.isSafeInteger(42)); // true
console.log(Number.isSafeInteger(9007199254740991)); // true(最大安全整数)
console.log(Number.isSafeInteger(9007199254740992)); // false(超出安全范围)
console.log(Number.isSafeInteger(42.5)); // false(非整数)
数值转换方法
Number()
将其他类型的值转换为数值。
console.log(Number("123")); // 123
console.log(Number("123.45")); // 123.45
console.log(Number("")); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number("0xFF")); // 255(十六进制)
console.log(Number("0b11")); // 3(二进制)
console.log(Number("0o7")); // 7(八进制)
console.log(Number("123abc")); // NaN(含非数字字符)
parseInt()
将字符串解析为整数。
console.log(parseInt("123")); // 123
console.log(parseInt("123.45")); // 123(忽略小数部分)
console.log(parseInt("")); // NaN
console.log(parseInt("0xFF")); // 255(十六进制)
console.log(parseInt("0b11")); // 0(不识别二进制前缀)
console.log(parseInt("123abc")); // 123(解析到非数字字符停止)
// 指定基数(进制)
console.log(parseInt("FF", 16)); // 255(十六进制)
console.log(parseInt("11", 2)); // 3(二进制)
console.log(parseInt("17", 8)); // 15(八进制)
parseFloat()
将字符串解析为浮点数。
console.log(parseFloat("123.45")); // 123.45
console.log(parseFloat("123")); // 123
console.log(parseFloat("")); // NaN
console.log(parseFloat("123.45abc")); // 123.45(解析到非数字字符停止)
console.log(parseFloat("0.1e2")); // 10(科学计数法)
数值格式化方法
Number原型上提供了几个格式化数值的方法:
toFixed()
格式化数值,保留指定位数的小数。
const num = 123.456789;
console.log(num.toFixed()); // "123"(默认不保留小数)
console.log(num.toFixed(2)); // "123.46"(保留2位小数,四舍五入)
console.log(num.toFixed(5)); // "123.45679"(保留5位小数,四舍五入)
console.log((0.1 + 0.2).toFixed(1)); // "0.3"(解决浮点数精度问题)
toExponential()
格式化数值为科学计数法表示,保留指定位数的小数。
const num = 123.456789;
console.log(num.toExponential()); // "1.23456789e+2"
console.log(num.toExponential(2)); // "1.23e+2"(保留2位小数,四舍五入)
console.log(num.toExponential(5)); // "1.23457e+2"(保留5位小数,四舍五入)
toPrecision()
格式化数值为指定精度(有效数字位数)。
const num = 123.456789;
console.log(num.toPrecision()); // "123.456789"(默认返回完整数值)
console.log(num.toPrecision(3)); // "123"(3位有效数字,四舍五入)
console.log(num.toPrecision(5)); // "123.46"(5位有效数字,四舍五入)
console.log(num.toPrecision(10)); // "123.4567890"(10位有效数字,不足补0)
toString()
将数值转换为字符串,可指定进制。
const num = 255;
console.log(num.toString()); // "255"(默认十进制)
console.log(num.toString(2)); // "11111111"(二进制)
console.log(num.toString(8)); // "377"(八进制)
console.log(num.toString(16)); // "ff"(十六进制)
console.log(num.toString(36)); // "73"(36进制,最大进制)
toLocaleString()
根据本地化格式将数值转换为字符串。
const num = 1234567.89;
console.log(num.toLocaleString()); // "1,234,567.89"(默认格式)
console.log(num.toLocaleString('zh-CN')); // "1,234,567.89"(中文格式)
console.log(num.toLocaleString('de-DE')); // "1.234.567,89"(德国格式)
// 使用选项参数
console.log(num.toLocaleString('zh-CN', { style: 'currency', currency: 'CNY' }));
// "¥1,234,567.89"(中国货币格式)
console.log(num.toLocaleString('en-US', { style: 'currency', currency: 'USD' }));
// "$1,234,567.89"(美国货币格式)
console.log(num.toLocaleString('zh-CN', { style: 'percent' }));
// "123,456,789%"(百分比格式)
console.log(num.toLocaleString('en-US', {
style: 'unit',
unit: 'kilometer-per-hour'
}));
// "1,234,567.89 km/h"(带单位格式)
处理数值精度问题
JavaScript使用IEEE 754标准的双精度浮点数表示数值,这可能导致一些精度问题:
console.log(0.1 + 0.2); // 0.30000000000000004(而不是0.3)
console.log(0.1 + 0.2 === 0.3); // false
解决精度问题的方法:
1. 使用toFixed()方法
console.log((0.1 + 0.2).toFixed(1)); // "0.3"
console.log(parseFloat((0.1 + 0.2).toFixed(10)) === 0.3); // true
2. 使用Number.EPSILON进行近似相等比较
function areAlmostEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(areAlmostEqual(0.1 + 0.2, 0.3)); // true
3. 转换为整数计算
function add(a, b) {
const factor = 10 ** 10;
return Math.round(a * factor + b * factor) / factor;
}
console.log(add(0.1, 0.2)); // 0.3
console.log(add(0.1, 0.2) === 0.3); // true
实际应用示例
1. 金融计算
function calculateTax(amount, rate) {
// 转换为整数计算,避免浮点数精度问题
const amountInCents = Math.round(amount * 100);
const rateInBasis = Math.round(rate * 10000);
const taxInCents = (amountInCents * rateInBasis) / 10000;
return Math.round(taxInCents) / 100;
}
const price = 19.99;
const taxRate = 0.08;
console.log(calculateTax(price, taxRate)); // 1.6
2. 数据验证
function validateNumericInput(input, options = {}) {
const {
min = Number.MIN_SAFE_INTEGER,
max = Number.MAX_SAFE_INTEGER,
integer = false
} = options;
const num = Number(input);
if (Number.isNaN(num)) {
return { valid: false, message: "请输入有效的数字" };
}
if (!Number.isFinite(num)) {
return { valid: false, message: "数值超出范围" };
}
if (integer && !Number.isInteger(num)) {
return { valid: false, message: "请输入整数" };
}
if (num < min) {
return { valid: false, message: `数值不能小于 ${min}` };
}
if (num > max) {
return { valid: false, message: `数值不能大于 ${max}` };
}
return { valid: true, value: num };
}
console.log(validateNumericInput("123")); // { valid: true, value: 123 }
console.log(validateNumericInput("abc")); // { valid: false, message: "请输入有效的数字" }
console.log(validateNumericInput("123.45", { integer: true }));
// { valid: false, message: "请输入整数" }
console.log(validateNumericInput("5", { min: 10 }));
// { valid: false, message: "数值不能小于 10" }
3. 格式化显示
function formatNumber(num, options = {}) {
const {
style = 'decimal',
currency,
precision,
locale = 'zh-CN'
} = options;
const opts = { style };
if (style === 'currency' && currency) {
opts.currency = currency;
}
if (precision !== undefined) {
if (style === 'percent') {
opts.minimumFractionDigits = precision;
opts.maximumFractionDigits = precision;
} else if (style === 'decimal' || style === 'currency') {
opts.minimumFractionDigits = precision;
opts.maximumFractionDigits = precision;
}
}
return num.toLocaleString(locale, opts);
}
// 使用示例
console.log(formatNumber(1234.567)); // "1,234.567"
console.log(formatNumber(1234.567, { precision: 2 })); // "1,234.57"
console.log(formatNumber(0.1234, { style: 'percent', precision: 2 })); // "12.34%"
console.log(formatNumber(1234.567, { style: 'currency', currency: 'CNY' })); // "¥1,234.57"
4. 数值范围映射
function mapRange(value, inMin, inMax, outMin, outMax) {
// 将一个范围内的数值映射到另一个范围
return (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
}
// 示例:将0-100的温度映射到0-1的进度值
console.log(mapRange(25, 0, 100, 0, 1)); // 0.25
console.log(mapRange(50, 0, 100, 0, 1)); // 0.5
// 示例:将角度(0-360)映射到颜色值(0-255)
console.log(mapRange(180, 0, 360, 0, 255)); // 127.5
BigInt类型
对于超出Number.MAX_SAFE_INTEGER范围的整数,JavaScript提供了BigInt类型:
// 创建BigInt
const bigInt1 = 9007199254740991n; // 使用n后缀
const bigInt2 = BigInt("9007199254740991"); // 使用BigInt()函数
const bigInt3 = BigInt("0x1fffffffffffff"); // 支持十六进制
console.log(bigInt1); // 9007199254740991n
console.log(bigInt2); // 9007199254740991n
console.log(bigInt3); // 9007199254740991n
// BigInt运算
console.log(bigInt1 + 1n); // 9007199254740992n
console.log(bigInt1 * 2n); // 18014398509481982n
console.log(bigInt1 / 2n); // 4503599627370495n(整数除法,没有小数部分)
// BigInt与Number的区别
console.log(typeof 123); // "number"
console.log(typeof 123n); // "bigint"
// 不能混合运算
// console.log(123n + 456); // TypeError: Cannot mix BigInt and other types
// 需要显式转换
console.log(123n + BigInt(456)); // 579n
console.log(Number(123n) + 456); // 579
Math对象与数值计算
除了Number对象,JavaScript还提供了Math对象,用于执行数学计算:
// 常量
console.log(Math.PI); // 3.141592653589793
console.log(Math.E); // 2.718281828459045
// 基本运算
console.log(Math.abs(-5)); // 5(绝对值)
console.log(Math.round(4.7)); // 5(四舍五入)
console.log(Math.ceil(4.3)); // 5(向上取整)
console.log(Math.floor(4.7)); // 4(向下取整)
console.log(Math.trunc(4.7)); // 4(截断小数部分)
// 最大值和最小值
console.log(Math.max(1, 3, 2)); // 3
console.log(Math.min(1, 3, 2)); // 1
// 幂运算和对数
console.log(Math.pow(2, 3)); // 8(2的3次方)
console.log(Math.sqrt(16)); // 4(平方根)
console.log(Math.cbrt(27)); // 3(立方根)
console.log(Math.log(Math.E)); // 1(自然对数)
console.log(Math.log10(100)); // 2(以10为底的对数)
console.log(Math.log2(8)); // 3(以2为底的对数)
// 三角函数
console.log(Math.sin(Math.PI / 2)); // 1(正弦)
console.log(Math.cos(Math.PI)); // -1(余弦)
console.log(Math.tan(Math.PI / 4)); // 0.9999999999999999(正切)
// 随机数
console.log(Math.random()); // 0到1之间的随机数(不包括1)
生成随机数
使用Math.random()生成各种范围的随机数:
// 生成0到1之间的随机数(不包括1)
function random() {
return Math.random();
}
// 生成min到max之间的随机整数(包括min和max)
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 生成min到max之间的随机浮点数(包括min,不包括max)
function randomFloat(min, max) {
return Math.random() * (max - min) + min;
}
// 示例
console.log(random()); // 例如:0.7564321254789632
console.log(randomInt(1, 10)); // 例如:7
console.log(randomFloat(1, 10)); // 例如:5.432156789
常见错误和最佳实践
常见错误
忽略NaN的特性:
// 错误 if (x === NaN) { // 永远为false,因为NaN不等于任何值,包括它自己 // ... } // 正确 if (Number.isNaN(x)) { // ... }
忽略浮点数精度问题:
// 错误 if (0.1 + 0.2 === 0.3) { // false,因为0.1 + 0.2 = 0.30000000000000004 // ... } // 正确 if (Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON) { // ... }
使用parseInt()不指定基数:
// 不推荐 parseInt("08"); // 在某些旧版本JavaScript中可能返回0,因为"08"被当作八进制处理 // 推荐 parseInt("08", 10); // 始终返回8
最佳实践
使用Number.isNaN()代替全局isNaN():
// 不推荐 isNaN("abc"); // true,因为"abc"转换为数值后是NaN // 推荐 Number.isNaN("abc"); // false,因为"abc"不是NaN Number.isNaN(Number("abc")); // true
处理金融计算时避免浮点数精度问题:
// 不推荐 const total = price + price * taxRate; // 推荐 const total = Math.round((price + price * taxRate) * 100) / 100;
使用Number.isSafeInteger()检查大整数:
// 不推荐 if (Number.isInteger(id)) { // ... } // 推荐 if (Number.isSafeInteger(id)) { // ... }
使用BigInt处理大整数:
// 不推荐 const largeNumber = 9007199254740992; // 可能不精确 // 推荐 const largeNumber = 9007199254740992n;
使用toFixed()时注意返回字符串:
// 不推荐 const roundedValue = value.toFixed(2); // 返回字符串 const result = roundedValue * 2; // 字符串隐式转换为数值 // 推荐 const roundedValue = Number(value.toFixed(2)); const result = roundedValue * 2;
总结
JavaScript的Number对象提供了丰富的属性和方法,用于处理数值:
- 常量:MAX_VALUE, MIN_VALUE, MAX_SAFE_INTEGER, MIN_SAFE_INTEGER, POSITIVE_INFINITY, NEGATIVE_INFINITY, NaN, EPSILON
- 检测方法:isFinite(), isInteger(), isNaN(), isSafeInteger()
- 转换方法:Number(), parseInt(), parseFloat()
- 格式化方法:toFixed(), toExponential(), toPrecision(), toString(), toLocaleString()
对于超出安全整数范围的数值,可以使用BigInt类型。
处理数值时,需要注意浮点数精度问题,特别是在金融计算和相等性比较中。
Math对象提供了额外的数学函数和常量,用于执行各种数学计算。
通过理解和正确使用这些工具,可以有效地处理JavaScript中的数值操作。
练习
编写一个函数,将数字格式化为货币字符串,支持不同的货币符号和小数位数。
实现一个函数,计算两个大数的精确加法(考虑浮点数精度问题)。
创建一个随机密码生成器,可以指定密码长度和包含的字符类型。
编写一个函数,判断一个数是否为素数。
实现一个简单的计算器,支持基本的算术运算和处理精度问题。