# 数字处理模块
数字处理模块提供了货币格式化、精确运算、随机数生成等功能,特别解决了JavaScript浮点数运算精度问题。
## 引用方式
### ES6 模块引用
```javascript
import sinma from 'sinmajs';
// 或者使用解构赋值
import { formatCurrency, add, subtract, multiply, divide } from 'sinmajs';
```
### CommonJS 引用
```javascript
const sinma = require('sinmajs');
```
### 浏览器直接引用
```html
<script src="https://unpkg.com/sinmajs@latest/dist/sinma.min.js"></script>
<script>
// 直接使用 sinma 对象
console.log(sinma.formatCurrency(1234.56));
</script>
```
## API 列表
### formatCurrency(amount, currency) - 货币格式化
将数字格式化为货币格式,支持千分位分隔符和小数点。
#### 参数
- `amount` {number} - 金额数值
- `currency` {string} - 货币符号,默认 `'¥'`
#### 返回值
- {string} - 格式化后的货币字符串
#### 功能代码
```javascript
function formatCurrency(amount, currency = '¥') {
if (!this.isValidNumber(amount)) return '0.00';
return currency + Number(amount).toLocaleString('zh-CN', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
}
```
#### 使用方法
```javascript
sinma.formatCurrency(1234.56); // '¥1,234.56'
sinma.formatCurrency(1000000, '$'); // '$1,000,000.00'
sinma.formatCurrency(999.9, '€'); // '€999.90'
sinma.formatCurrency(0); // '¥0.00'
sinma.formatCurrency(-1234.56); // '¥-1,234.56'
```
#### 使用范例
```javascript
// 电商商品价格显示
function formatProductPrice(price, currency = '¥') {
if (price === 0) {
return '免费';
}
return sinma.formatCurrency(price, currency);
}
// 订单总额计算
function calculateOrderTotal(items) {
const total = items.reduce((sum, item) => sum + (item.price * item.quantity), 0);
return {
total: total,
formatted: sinma.formatCurrency(total),
items: items.map(item => ({
...item,
subtotal: sinma.formatCurrency(item.price * item.quantity)
}))
};
}
const order = [
{ name: '苹果', price: 5.99, quantity: 3 },
{ name: '香蕉', price: 2.49, quantity: 2 }
];
console.log(calculateOrderTotal(order));
// {
// total: 22.95,
// formatted: '¥22.95',
// items: [
// { name: '苹果', price: 5.99, quantity: 3, subtotal: '¥17.97' },
// { name: '香蕉', price: 2.49, quantity: 2, subtotal: '¥4.98' }
// ]
// }
// 多币种价格显示
function formatMultiCurrency(amount) {
return {
cny: sinma.formatCurrency(amount, '¥'),
usd: sinma.formatCurrency(amount / 7.2, '$'),
eur: sinma.formatCurrency(amount / 8.1, '€')
};
}
```
---
### add(a, b) - 精确加法
执行精确的加法运算,避免JavaScript浮点数精度问题。
#### 参数
- `a` {number} - 加数
- `b` {number} - 被加数
#### 返回值
- {number} - 精确的加法结果
#### 功能代码
```javascript
function add(a, b) {
const factor = Math.pow(10, Math.max(this.getDecimalLength(a), this.getDecimalLength(b)));
return (Math.round(a * factor) + Math.round(b * factor)) / factor;
}
function getDecimalLength(num) {
const str = num.toString();
const index = str.indexOf('.');
return index === -1 ? 0 : str.length - index - 1;
}
```
#### 使用方法
```javascript
// JavaScript 原生问题
0.1 + 0.2; // 0.30000000000000004
// sinmajs 精确运算
sinma.add(0.1, 0.2); // 0.3
sinma.add(1.1, 2.2); // 3.3
sinma.add(123.456, 78.9); // 202.356
sinma.add(-10.5, 5.25); // -5.25
```
#### 使用范例
```javascript
// 购物车总价计算
function calculateCartTotal(items) {
return items.reduce((total, item) => {
const itemTotal = sinma.multiply(item.price, item.quantity);
return sinma.add(total, itemTotal);
}, 0);
}
// 财务报表计算
class FinancialCalculator {
constructor() {
this.total = 0;
}
addIncome(amount) {
this.total = sinma.add(this.total, amount);
return this;
}
addExpense(amount) {
this.total = sinma.subtract(this.total, amount);
return this;
}
getBalance() {
return this.total;
}
getFormattedBalance() {
return sinma.formatCurrency(this.total);
}
}
const calc = new FinancialCalculator();
calc.addIncome(1000.1)
.addIncome(500.2)
.addExpense(200.15);
console.log(calc.getFormattedBalance()); // '¥1,300.15'
```
---
### subtract(a, b) - 精确减法
执行精确的减法运算。
#### 参数
- `a` {number} - 被减数
- `b` {number} - 减数
#### 返回值
- {number} - 精确的减法结果
#### 功能代码
```javascript
function subtract(a, b) {
return this.add(a, -b);
}
```
#### 使用方法
```javascript
sinma.subtract(1, 0.9); // 0.1 (而不是 0.09999999999999998)
sinma.subtract(5.5, 2.3); // 3.2
sinma.subtract(10, 15); // -5
sinma.subtract(0, 5); // -5
```
#### 使用范例
```javascript
// 库存扣减计算
function updateInventory(currentStock, soldQuantity) {
const remaining = sinma.subtract(currentStock, soldQuantity);
return {
previous: currentStock,
sold: soldQuantity,
remaining: remaining,
needRestock: remaining < 10
};
}
// 账户余额计算
function processTransaction(balance, amount, type) {
let newBalance;
if (type === 'debit') {
newBalance = sinma.subtract(balance, amount);
} else {
newBalance = sinma.add(balance, amount);
}
return {
previousBalance: sinma.formatCurrency(balance),
transactionAmount: sinma.formatCurrency(amount),
newBalance: sinma.formatCurrency(newBalance),
type: type
};
}
```
---
### multiply(a, b) - 精确乘法
执行精确的乘法运算。
#### 参数
- `a` {number} - 乘数
- `b` {number} - 被乘数
#### 返回值
- {number} - 精确的乘法结果
#### 功能代码
```javascript
function multiply(a, b) {
const factor = Math.pow(10, this.getDecimalLength(a) + this.getDecimalLength(b));
return (Math.round(a * factor) * Math.round(b * factor)) / (factor * factor);
}
```
#### 使用方法
```javascript
sinma.multiply(0.2, 3); // 0.6 (而不是 0.6000000000000001)
sinma.multiply(1.1, 2.2); // 2.42
sinma.multiply(123.45, 0.1); // 12.345
sinma.multiply(-5, 3.3); // -16.5
```
#### 使用范例
```javascript
// 商品价格计算(含税)
function calculatePriceWithTax(price, taxRate) {
const tax = sinma.multiply(price, taxRate);
const totalPrice = sinma.add(price, tax);
return {
basePrice: sinma.formatCurrency(price),
tax: sinma.formatCurrency(tax),
totalPrice: sinma.formatCurrency(totalPrice),
taxRate: `${sinma.multiply(taxRate, 100)}%`
};
}
console.log(calculatePriceWithTax(99.99, 0.13));
// {
// basePrice: '¥99.99',
// tax: '¥12.999870',
// totalPrice: '¥112.989870',
// taxRate: '13%'
// }
// 折扣价格计算
function applyDiscount(originalPrice, discountPercentage) {
const discountAmount = sinma.multiply(originalPrice, discountPercentage / 100);
const finalPrice = sinma.subtract(originalPrice, discountAmount);
return {
original: sinma.formatCurrency(originalPrice),
discount: `${discountPercentage}%`,
saved: sinma.formatCurrency(discountAmount),
final: sinma.formatCurrency(finalPrice)
};
}
```
---
### divide(a, b) - 精确除法
执行精确的除法运算。
#### 参数
- `a` {number} - 被除数
- `b` {number} - 除数
#### 返回值
- {number} - 精确的除法结果
#### 异常
- 除数为0时抛出 `Error: Division by zero`
#### 功能代码
```javascript
function divide(a, b) {
if (b === 0) throw new Error('Division by zero');
const factorA = Math.pow(10, this.getDecimalLength(a));
const factorB = Math.pow(10, this.getDecimalLength(b));
return (Math.round(a * factorA) / Math.round(b * factorB));
}
```
#### 使用方法
```javascript
sinma.divide(1, 3); // 0.3333333333333333
sinma.divide(10, 3); // 3.3333333333333335
sinma.divide(0.6, 0.2); // 3 (而不是 2.9999999999999996)
sinma.divide(100, 0); // Error: Division by zero
```
#### 使用范例
```javascript
// 平均值计算
function calculateAverage(numbers) {
if (numbers.length === 0) return 0;
const sum = numbers.reduce((acc, num) => sinma.add(acc, num), 0);
return sinma.divide(sum, numbers.length);
}
const scores = [85.5, 92.3, 78.9, 96.1];
console.log(calculateAverage(scores)); // 88.2
// 单价计算
function calculateUnitPrice(totalPrice, quantity) {
try {
const unitPrice = sinma.divide(totalPrice, quantity);
return {
success: true,
unitPrice: sinma.formatCurrency(unitPrice),
totalPrice: sinma.formatCurrency(totalPrice),
quantity: quantity
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// 比例计算
function calculatePercentage(part, total) {
if (total === 0) return 0;
return sinma.multiply(sinma.divide(part, total), 100);
}
```
---
### randomInt(min, max) - 生成随机整数
生成指定范围内的随机整数(包含边界值)。
#### 参数
- `min` {number} - 最小值,默认 `0`
- `max` {number} - 最大值,默认 `100`
#### 返回值
- {number} - 指定范围内的随机整数
#### 功能代码
```javascript
function randomInt(min = 0, max = 100) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
```
#### 使用方法
```javascript
sinma.randomInt(); // 0-100之间的随机整数
sinma.randomInt(1, 10); // 1-10之间的随机整数
sinma.randomInt(-5, 5); // -5到5之间的随机整数
sinma.randomInt(100, 200); // 100-200之间的随机整数
```
#### 使用范例
```javascript
// 生成验证码
function generateNumericCode(length = 6) {
let code = '';
for (let i = 0; i < length; i++) {
code += sinma.randomInt(0, 9).toString();
}
return code;
}
console.log(generateNumericCode()); // '385726'
// 随机抽奖
function drawLottery(participants) {
if (participants.length === 0) return null;
const winnerIndex = sinma.randomInt(0, participants.length - 1);
return {
winner: participants[winnerIndex],
index: winnerIndex,
total: participants.length
};
}
// 生成测试数据
function generateTestScores(count) {
return Array.from({ length: count }, () => sinma.randomInt(60, 100));
}
// 随机颜色生成
function generateRandomColor() {
const r = sinma.randomInt(0, 255);
const g = sinma.randomInt(0, 255);
const b = sinma.randomInt(0, 255);
return `rgb(${r}, ${g}, ${b})`;
}
// 模拟骰子
function rollDice(sides = 6, count = 1) {
return Array.from({ length: count }, () => sinma.randomInt(1, sides));
}
console.log(rollDice(6, 2)); // [4, 1] (两个六面骰子的结果)
```
---
### isValidNumber(value) - 数字验证
检查值是否为有效的数字类型。
#### 参数
- `value` {*} - 待检查的值
#### 返回值
- {boolean} - 是有效数字返回 `true`,否则返回 `false`
#### 功能代码
```javascript
function isValidNumber(value) {
return typeof value === 'number' && !isNaN(value);
}
```
#### 使用方法
```javascript
sinma.isValidNumber(123); // true
sinma.isValidNumber(0); // true
sinma.isValidNumber(-123); // true
sinma.isValidNumber(3.14); // true
sinma.isValidNumber('123'); // false
sinma.isValidNumber(NaN); // false
sinma.isValidNumber(null); // false
sinma.isValidNumber(undefined); // false
```
#### 使用范例
```javascript
// 输入验证
function validateNumberInput(input, min = 0, max = Infinity) {
if (!sinma.isValidNumber(input)) {
return { valid: false, error: '请输入有效的数字' };
}
if (input < min) {
return { valid: false, error: `数值不能小于 ${min}` };
}
if (input > max) {
return { valid: false, error: `数值不能大于 ${max}` };
}
return { valid: true, value: input };
}
// 安全的数学运算
function safeAdd(a, b) {
if (!sinma.isValidNumber(a) || !sinma.isValidNumber(b)) {
throw new Error('参数必须为有效数字');
}
return sinma.add(a, b);
}
// 数组中数字过滤
function filterValidNumbers(array) {
return array.filter(sinma.isValidNumber);
}
```
## 高级用法示例
### 精确运算链式计算
```javascript
// 复合财务计算
function calculateCompoundInterest(principal, rate, periods) {
let result = principal;
for (let i = 0; i < periods; i++) {
const interest = sinma.multiply(result, rate);
result = sinma.add(result, interest);
}
return {
principal: sinma.formatCurrency(principal),
finalAmount: sinma.formatCurrency(result),
totalInterest: sinma.formatCurrency(sinma.subtract(result, principal)),
rate: `${sinma.multiply(rate, 100)}%`,
periods: periods
};
}
console.log(calculateCompoundInterest(10000, 0.05, 3));
// 复利计算:本金10000,年利率5%,3年
```
### 价格计算系统
```javascript
class PriceCalculator {
constructor(basePrice) {
this.basePrice = basePrice;
this.adjustments = [];
}
addTax(rate) {
const tax = sinma.multiply(this.basePrice, rate);
this.adjustments.push({ type: 'tax', amount: tax, rate });
return this;
}
addDiscount(percentage) {
const discount = sinma.multiply(this.basePrice, percentage / 100);
this.adjustments.push({ type: 'discount', amount: -discount, percentage });
return this;
}
addFee(amount) {
this.adjustments.push({ type: 'fee', amount });
return this;
}
calculate() {
const totalAdjustments = this.adjustments.reduce((sum, adj) =>
sinma.add(sum, adj.amount), 0);
const finalPrice = sinma.add(this.basePrice, totalAdjustments);
return {
basePrice: sinma.formatCurrency(this.basePrice),
adjustments: this.adjustments.map(adj => ({
...adj,
amount: sinma.formatCurrency(Math.abs(adj.amount))
})),
totalAdjustments: sinma.formatCurrency(totalAdjustments),
finalPrice: sinma.formatCurrency(finalPrice)
};
}
}
const price = new PriceCalculator(100)
.addTax(0.13)
.addDiscount(10)
.addFee(5)
.calculate();
```
### 统计计算工具
```javascript
function calculateStatistics(numbers) {
const validNumbers = numbers.filter(sinma.isValidNumber);
if (validNumbers.length === 0) {
return { error: '没有有效的数字数据' };
}
const sum = validNumbers.reduce((acc, num) => sinma.add(acc, num), 0);
const average = sinma.divide(sum, validNumbers.length);
const min = Math.min(...validNumbers);
const max = Math.max(...validNumbers);
// 计算方差和标准差
const variance = validNumbers.reduce((acc, num) => {
const diff = sinma.subtract(num, average);
return sinma.add(acc, sinma.multiply(diff, diff));
}, 0) / validNumbers.length;
const standardDeviation = Math.sqrt(variance);
return {
count: validNumbers.length,
sum: sum,
average: average,
min: min,
max: max,
variance: variance,
standardDeviation: standardDeviation
};
}
```
## 性能优化建议
1. **批量计算**: 对于大量数据,考虑使用批量计算函数
2. **缓存结果**: 相同的计算结果可以缓存避免重复计算
3. **精度控制**: 根据实际需要选择合适的精度,避免过度计算
4. **错误处理**: 在关键计算中添加适当的错误处理
## 注意事项
1. **除零错误**: `divide` 函数会在除数为0时抛出异常
2. **数值范围**: JavaScript数值范围限制仍然适用
3. **精度限制**: 虽然解决了常见的精度问题,但极端情况下仍可能有误差
4. **性能权衡**: 精确运算相比原生运算会有轻微性能损失
## 相关模块
- [数据验证模块](./validator.md) - 提供数字验证功能
- [字符串模块](./string.md) - 提供数字到字符串的转换功能
- [工具函数模块](./utils.md) - 提供其他数学工具函数
