单位系统
a-calc 提供了完整的单位系统,包括:
- 单位计算:带单位的数值参与运算
- 单位转换:不同单位之间的换算(分→元、米→千米等)
- 单位位置格式化:控制单位在输出中的显示位置
单位计算
启用单位计算
使用 _unit: true 选项启用单位计算:
import { calc } from 'a-calc'
calc('100元 + 50元', { _unit: true }) // '150元'
calc('10kg + 5kg', { _unit: true }) // '15kg'
calc('50% + 30%', { _unit: true }) // '80%'单位提取规则
a-calc 会自动从数值后面提取单位:
calc('100元', { _unit: true }) // '100元'
calc('99.9折', { _unit: true }) // '99.9折'
calc('15%', { _unit: true }) // '15%'
calc('3.14π', { _unit: true }) // '3.14π'注意
单位必须紧跟在数字后面,不能有空格:
calc('100元', { _unit: true }) // ✓ 正确
calc('100 元', { _unit: true }) // ✗ 错误,单位会被忽略复杂表达式
单位计算支持复杂的数学表达式:
calc('(100元 + 50元) * 2', { _unit: true }) // '300元'
calc('100元 * 3 - 50元', { _unit: true }) // '250元'
calc('1000元 / 4', { _unit: true }) // '250元'
calc('2 ** 10 字节', { _unit: true }) // '1024字节'变量中的单位
变量值也可以包含单位:
calc('price + discount', {
price: '100元',
discount: '20元',
_unit: true
}) // '120元'
calc('total * rate', {
total: '1000元',
rate: 0.8,
_unit: true
}) // '800元'移除单位
使用 !u 或 !uh(无参数时)移除结果中的单位:
calc('100元 + 50元', { _unit: true }) // '150元'
calc('100元 + 50元 | !u', { _unit: true }) // '150'
calc('100元 + 50元 | !uh', { _unit: true }) // '150' (等效)单位与格式化结合
单位计算可以与格式化选项一起使用:
// 保留小数
calc('100.5元 + 50.3元 | =2', { _unit: true }) // '150.80元'
// 千分位
calc('1000元 + 500元 | ,', { _unit: true }) // '1,500元'
// 组合
calc('10000元 * 1.5 | =2,', { _unit: true }) // '15,000.00元'单位位置格式化
单位位置语法用于在格式化结果中添加货币符号或其他单位,并控制其显示位置。
语法概览
| 语法 | 说明 | 示例 |
|---|---|---|
!u:单位 | 显示单位(位置可配置) | 100 → 100元 |
!ua:单位 | 单位在数字后 (after) | 100 → 100元 |
!ub:单位 | 单位在数字前 (before) | 100 → $100 |
!um:单位 | 单位在中间 (middle) | -100 → -$100 |
!uh:单位 | 只转换,不显示单位 | 100分 → 1 |
!u:unit - 显示单位(推荐)
最简洁的单位语法,默认单位在数字后面:
calc('100 | !u:元') // '100元'
calc('100.5 | =2 !u:元') // '100.50元'可通过 set_config 设置全局默认位置:
import { calc, set_config } from 'a-calc'
set_config({ _unit_default_position: 'before' })
calc('100 | !u:$') // '$100'
set_config({ _unit_default_position: 'middle' })
calc('-100 | + !u:$') // '-$100'
set_config({ _unit_default_position: 'after' })
calc('100 | !u:元') // '100元'!ua:unit - 单位在数字后 (after)
calc('100 | !ua:元') // '100元'
calc('-50 | + !ua:元') // '-50元'
calc('1234.5 | =2, !ua:元') // '1,234.50元'!ub:unit - 单位在数字前 (before)
calc('100 | !ub:$') // '$100'
calc('-50 | !ub:$') // '$-50'
calc('100 | + !ub:$') // '$+100'
calc('1234.5 | =2, !ub:$') // '$1,234.50'!um:unit - 单位在中间 (middle)
将货币符号放在正负号和数字之间,常用于金融数据展示:
calc('8 | + !um:$') // '+$8'
calc('-6 | + !um:$') // '-$6'
// 不同货币
calc('100 | + !um:¥') // '+¥100'
calc('-50 | + !um:€') // '-€50'
// 结合千分位和小数
calc('12345 | +, !um:$') // '+$12,345'
calc('-12345.67 | +=2, !um:$') // '-$12,345.67'
// 多字符单位
calc('100 | + !um:USD') // '+USD100'中间位置说明
当没有符号时,!um 效果等同于 !ub:
calc('100 | !um:$') // '$100' (无符号,同 !ub)
calc('100 | + !um:$') // '+$100' (有符号,在中间)!uh:unit - 只转换不显示
进行单位转换但不在结果中显示单位:
calc('100 | =2 !uh:元', {
_unit_convert_out: { '元': { '分': 0.01 } }
}) // '1.00' (100分转换为1元,但不显示"元")位置对比
const value = '-1234.56'
calc(`${value} | + !ua:$`) // '-1234.56$' (数字后)
calc(`${value} | + !ub:$`) // '$-1234.56' (数字前,符号在单位后)
calc(`${value} | + !um:$`) // '-$1234.56' (中间,符号在单位前)@ 变量引用
使用 @ 前缀在单位语法中引用变量值:
// 基础引用
calc('100 | !ua:@unit', { unit: '元' }) // '100元'
calc('100 | !ub:@currency', { currency: '$' }) // '$100'
// 变量路径
calc('100 | !ua:@config.unit', {
config: { unit: '元' }
}) // '100元'
// 结合转换
calc('100 | =2 !ua:@outUnit', {
outUnit: '元',
_unit_convert_out: { '元': { '分': 0.01 } }
}) // '1.00元'
// 同时指定输入输出单位
calc('100 | =2 !ua:@outUnit:@inUnit', {
outUnit: '元',
inUnit: '分',
_unit_convert_out: { '元': { '分': 0.01, '厘': 0.001 } }
}) // '1.00元'单位转换
单位转换用于将数值从一个单位换算到另一个单位(如分→元、米→千米)。
配置方式
_unit_convert_out(推荐)
以输出单位为 key 配置转换规则:
calc('100 | =2 !ua:元', {
_unit_convert_out: {
'元': { '分': 0.01 } // 分 × 0.01 = 元
}
}) // '1.00元' (100分 → 1元)_unit_convert_in
以输入单位为 key 配置转换规则(会自动转换为 _unit_convert_out 格式):
calc('100 | =2 !ua:元', {
_unit_convert_in: {
'分': { '元': 0.01 }
}
}) // '1.00元'推荐使用 _unit_convert_out
_unit_convert_out 以输出单位为 key,查找时间复杂度为 O(1),性能更优。
语法方式
在格式字符串中直接指定转换:
// 只指定输出单位(自动查找输入单位)
calc('100 | =2 !ua:元', {
_unit_convert_out: { '元': { '分': 0.01 } }
}) // '1.00元'
// 同时指定输出和输入单位
calc('100 | =2 !ua:元:分', {
_unit_convert_out: { '元': { '分': 0.01, '厘': 0.001 } }
}) // '1.00元'
// 只转换不显示单位
calc('100 | =2 !uh:元', {
_unit_convert_out: { '元': { '分': 0.01 } }
}) // '1.00'转换规则格式
转换规则支持多种格式:
_unit_convert_out: {
'元': {
// 1. 数字:直接作为乘数
'分': 0.01, // value × 0.01
// 2. 对象 mul:乘以指定值
'角': { mul: 0.1 }, // value × 0.1
// 3. 对象 div:除以指定值
'厘': { div: 1000 }, // value ÷ 1000
// 4. 对象组合:mul/div → plus/minus
'特殊': {
mul: 0.01, // 先乘
plus: 1 // 再加
},
// 5. 函数:完全自定义
'CNY': (value, inputUnit, outputUnit) => value / 7.2,
// 6. 对象 fn:自定义函数
'USD': {
fn: (value, inputUnit, outputUnit) => value / 7.2
}
}
}对象规则执行顺序:mul/div → plus/minus
// 例:华氏度转摄氏度 C = (F - 32) × 5/9
'℃': {
'℉': {
minus: 32, // 先减32
mul: 5/9 // 这样写不对!
}
}
// 正确写法:使用函数
'℃': {
'℉': (f) => (f - 32) * 5 / 9
}纯配置模式
不使用语法,完全通过配置项控制转换:
calc('100 | =2', {
_unit_convert_out: { '元': { '分': 0.01 } },
_unit_default_out: '元', // 默认输出单位
_unit_default_in: '分', // 默认输入单位
_unit_default_position: 'after' // 单位位置
}) // '1.00元'多输入单位选择
当一个输出单位对应多个输入单位时,使用 _unit_default_in 指定默认输入单位:
// 元可以从"分"或"厘"转换
calc('100 | =2 !ua:元', {
_unit_convert_out: { '元': { '分': 0.01, '厘': 0.001 } },
_unit_default_in: '分' // 默认从"分"转换
}) // '1.00元' (100分 → 1元)
calc('100 | =3 !ua:元', {
_unit_convert_out: { '元': { '分': 0.01, '厘': 0.001 } },
_unit_default_in: '厘' // 默认从"厘"转换
}) // '0.100元' (100厘 → 0.1元)
// 可以是数组,按顺序优先匹配
calc('100 | =2 !ua:元', {
_unit_convert_out: { '元': { '分': 0.01, '厘': 0.001 } },
_unit_default_in: ['分', '厘'] // 优先"分"
}) // '1.00元'智能匹配优先级
当只指定输出单位时,a-calc 按以下顺序匹配输入单位:
语法显式指定(最高优先级)
javascriptcalc('100 | !ua:元:厘', { ... }) // 使用"厘"_unit_default_in配置javascriptcalc('100 | !ua:元', { _unit_default_in: '分' }) // 使用"分"单一输入单位(自动使用)
javascriptcalc('100 | !ua:元', { _unit_convert_out: { '元': { '分': 0.01 } } // 只有"分" }) // 自动使用"分"多个输入单位且无法确定:不进行转换
单位位置映射
可以为不同的单位预设不同的显示位置。
在 _unit_convert_out 中配置
使用 _position 字段:
calc('100 | =2 !u:元', {
_unit_convert_out: {
'元': {
'分': 0.01,
_position: 'after' // 元在数字后
},
'$': {
'¢': 0.01,
_position: 'before' // $ 在数字前
}
}
}) // '1.00元'
calc('100 | =2 !u:$', {
_unit_convert_out: {
'$': {
'¢': 0.01,
_position: 'before'
}
}
}) // '$1.00'输入单位也可以有位置配置:
calc('100 | !u:分', {
_unit_convert_out: {
'元': {
'分': {
mul: 0.01,
_position: 'after' // 分的位置配置
}
}
}
}) // '100分'使用 _unit_position_map
直接配置单位到位置的映射(优先级高于 _unit_convert_out 中的配置):
calc('100 | !u:$', {
_unit_position_map: {
'$': 'before',
'€': 'middle',
'元': 'after'
}
}) // '$100'
calc('-100 | + !u:€', {
_unit_position_map: { '€': 'middle' }
}) // '-€100'位置优先级
从低到高:
_unit_default_position(全局默认)_unit_convert_out中的_position_unit_position_map- 显式语法
!ua:/!ub:/!um:(最高)
calc('100 | !ua:$', {
_unit_position_map: { '$': 'before' } // 被 !ua 覆盖
}) // '100$' (显式 !ua 优先)单位与千分位关联
可以为不同的单位配置不同的千分位格式,详见 千分位格式化 - 单位关联。
calc('1234567.89 | , !ua:€', {
_unit_thousands_map: { '€': 'eu' }
}) // '1.234.567,89€' (欧洲格式)
calc('1234567.89 | , !ua:$', {
_unit_convert_out: { '$': { _thousands: 'en' } }
}) // '1,234,567.89$' (英文/国际格式)配置项速查
| 配置项 | 类型 | 说明 |
|---|---|---|
_unit | boolean | 启用单位计算模式 |
_unit_convert_out | object | 单位转换映射(输出单位为 key) |
_unit_convert_in | object | 单位转换映射(输入单位为 key) |
_unit_default_out | string | string[] | 默认输出单位 |
_unit_default_in | string | string[] | 默认输入单位 |
_unit_default_position | 'after' | 'before' | 'middle' | 全局单位位置 |
_unit_position_map | object | 单位到位置的映射 |
_unit_thousands_map | object | 单位到千分位预设的映射 |
| 格式语法 | 说明 |
|---|---|
!u | 移除单位(无参数时) |
!u:unit | 显示单位(位置可配置) |
!ua:unit | 单位在数字后 |
!ub:unit | 单位在数字前 |
!um:unit | 单位在中间 |
!uh:unit | 只转换不显示单位 |
!u:output:input | 指定输入输出单位 |
!u:@var | 使用变量值作为单位 |
完整示例
多币种金融系统
const currencyOptions = {
_unit_convert_out: {
'元': {
'分': 0.01,
_position: 'after',
_thousands: 'wan' // 万进制千分位
},
'$': {
'¢': 0.01,
_position: 'before',
_thousands: 'en'
},
'€': {
'cent': 0.01,
_position: 'before',
_thousands: 'eu'
}
}
}
calc('12345678 | =2, !u:元', currencyOptions) // '1234,5678.00元'
calc('12345678 | =2, !u:$', currencyOptions) // '$123,456.78'
calc('12345678 | =2, !u:€', currencyOptions) // '€123.456,78'长度单位换算
const lengthOptions = {
_unit_convert_out: {
'千米': {
'米': { div: 1000 },
'厘米': { div: 100000 }
},
'米': {
'厘米': { div: 100 },
'毫米': { div: 1000 }
}
}
}
calc('5000 | =2 !ua:千米:米', lengthOptions) // '5.00千米'
calc('150 | =2 !ua:米:厘米', lengthOptions) // '1.50米'温度转换
const tempOptions = {
_unit_convert_out: {
'℃': {
'℉': (f) => (f - 32) * 5 / 9,
'K': (k) => k - 273.15
},
'℉': {
'℃': (c) => c * 9 / 5 + 32
}
}
}
calc('100 | =1 !ua:℃:℉', tempOptions) // '37.7℃' (100℉ → 37.7℃)
calc('0 | =1 !ua:℃:K', tempOptions) // '-273.1℃' (0K → -273.15℃)