# number

数字处理工具函数 / Number utilities

基于 big.js / Based on big.js

## Overview / 概述

提供一系列数字处理函数，包括精度计算、数字格式化、金钱格式化等。基于 [big.js](https://github.com/MikeMcl/big.js/) 库，解决 JavaScript 浮点数精度问题。

Provide a series of number handling functions including precision calculation, number formatting, money formatting, etc. Based on [big.js](https://github.com/MikeMcl/big.js/) to solve JavaScript floating point precision problems.

## Functions

### useNumber

返回实例化的 Big 对象 / Get Big instance

```ts
function useNumber(n: BigSource): Big
```

**Parameters / 参数**

| Name | Type | Description |
|------|------|-------------|
| `n` | `BigSource` | 数字或字符串 |

**Returns / 返回值**

- `Big`: Big.js 实例

**Example / 示例**

```ts
// 加法
useNumber('1').add('2').toNumber()      // 3

// 减法
useNumber('2').sub('1').toNumber()      // 1

// 乘法
useNumber(1).times(2).toNumber()        // 2

// 除法
useNumber(2).div(1).toNumber()          // 2

// 四舍五入
useNumber('1.5').round(0, 1).toNumber() // 2

// 精度计算
useNumber('0.1').add('0.2').toNumber()   // 0.3 (不会有精度问题)
```

---

### formatMoney

格式化金钱（万、亿）/ Format money (万/亿)

```ts
function formatMoney(num: number): string
```

**Parameters / 参数**

| Name | Type | Description |
|------|------|-------------|
| `num` | `number` | 要格式化的数字 |

**Returns / 返回值**

- `string`: 格式化后的金钱字符串

**Example / 示例**

```ts
// 小于等于4位
formatMoney(1234)     // '1234'

// 5-8位 (万)
formatMoney(12345)    // '1万2345'
formatMoney(10000)    // '1万'
formatMoney(1234567)  // '123万4567'

// 9-12位 (亿)
formatMoney(123456789)     // '1亿2345万6789'
formatMoney(100000000)     // '1亿'
formatMoney(100000001)     // '1亿1'

// 大于12位
formatMoney(9007199254740992)  // '90071992亿5474万992'
formatMoney(12345678901234)    // '1234亿5678万9012'
```

---

### formatNumber

格式化数字（千位分隔符）/ Format number with separator

```ts
function formatNumber(val: number | string, options?: FormatOptions): string
```

**Parameters / 参数**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `val` | `number \| string` | - | 要格式化的数字 |
| `options.precision` | `number` | `0` | 保留小数位数 |
| `options.thousandSeparator` | `string` | `,` | 千位分隔符 |
| `options.bit` | `number` | `3` | 分隔位数 |
| `options.roundMode` | `RoundingMode` | `1` | 舍入模式 |

**RoundingMode / 舍入模式**

| Mode | Description |
|------|-------------|
| 0 | 向下取整 |
| 1 | 四舍五入 |
| 2 | roundHalfEven |
| 3 | 向上取整 |

**Example / 示例**

```ts
// 千位分隔
formatNumber(1000)                       // '1,000'
formatNumber(1234567)                    // '1,234,567'

// 保留小数
formatNumber(1234.5678, { precision: 2 }) // '1,234.57'

// 自定义分隔符
formatNumber(1234567, { thousandSeparator: '-' }) // '1-234-567'

// 不同分隔位数
formatNumber(1234567, { bit: 4 }) // '123,4567'
```

---

### round

四舍五入（精度兼容）/ Round with precision

```ts
function round(m: BigSource, dp: number, rm?: RoundingMode): number
```

**Parameters / 参数**

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `m` | `BigSource` | - | 数字 |
| `dp` | `number` | - | 保留位数 |
| `rm` | `RoundingMode` | `1` | 舍入模式 |

**Example / 示例**

```ts
// 四舍五入
round(5.23, 1)  // 5.2

// 向上取整
round(5.23, 1, 3)  // 5.3

// 向下取整
round(5.23, 1, 0)  // 5.2

// 精度计算
round(0.1 + 0.2, 1)  // 0.3
```

---

## Use Cases / 使用场景

### 价格显示 / Price Display

```ts
// 商品价格
formatMoney(product.price)

// 订单金额
formatMoney(order.totalAmount)

// 用户余额
formatMoney(user.balance)
```

### 数字格式化 / Number Formatting

```ts
// 统计数据
formatNumber(userCount)  // '1,234'

// 精确小数
formatNumber(price, { precision: 2 })  // '1,234.56'

// 银行卡号
formatNumber(cardNumber, { bit: 4, thousandSeparator: ' ' }) // '1234 5678 9012 3456'
```

### 精度计算 / Precision Calculation

```ts
// 金额计算
const total = useNumber(price)
  .times(quantity)
  .plus(shippingFee)
  .minus(discount)
  .toNumber()

// 比例计算
const percent = useNumber(value)
  .div(total)
  .times(100)
  .round(2)
  .toNumber()
```

### 计数器动画 / Counter Animation

```ts
function animateCounter(target: number, duration: number = 1000) {
  const start = 0
  const startTime = Date.now()

  const animate = () => {
    const elapsed = Date.now() - startTime
    const progress = Math.min(elapsed / duration, 1)

    // 使用 easeOut 函数
    const easeOut = 1 - Math.pow(1 - progress, 3)
    const current = useNumber(target).times(easeOut).toNumber()

    element.textContent = formatNumber(Math.round(current))

    if (progress < 1) {
      requestAnimationFrame(animate)
    }
  }

  requestAnimationFrame(animate)
}
```
