Created
December 24, 2015 11:45
-
-
Save tonyc726/00c829a54a40cf80409f to your computer and use it in GitHub Desktop.
JS数字金额大写转换
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var digitUppercase = function(n) { | |
var fraction = ['角', '分']; | |
var digit = [ | |
'零', '壹', '贰', '叁', '肆', | |
'伍', '陆', '柒', '捌', '玖' | |
]; | |
var unit = [ | |
['元', '万', '亿'], | |
['', '拾', '佰', '仟'] | |
]; | |
var head = n < 0 ? '欠' : ''; | |
n = Math.abs(n); | |
var s = ''; | |
for (var i = 0; i < fraction.length; i++) { | |
s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, ''); | |
} | |
s = s || '整'; | |
n = Math.floor(n); | |
for (var i = 0; i < unit[0].length && n > 0; i++) { | |
var p = ''; | |
for (var j = 0; j < unit[1].length && n > 0; j++) { | |
p = digit[n % 10] + unit[1][j] + p; | |
n = Math.floor(n / 10); | |
} | |
s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s; | |
} | |
return head + s.replace(/(零.)*零元/, '元') | |
.replace(/(零.)+/g, '零') | |
.replace(/^整$/, '零元整'); | |
}; | |
console.log(digitUppercase(7682.01)); //柒仟陆佰捌拾贰元壹分 | |
console.log(digitUppercase(7682)); //柒仟陆佰捌拾贰元整 | |
console.log(digitUppercase(951434677682.00)); //玖仟伍佰壹拾肆亿叁仟肆佰陆拾柒万柒仟陆佰捌拾贰元整 |
100个赞
标准的财务数字大写,如果是负数的话应该这么写:
比如 -1.00
大写: (负数)壹元整
代码优化如下:
var head = n < 0 ? '欠' : '(负数)';
// 对数字先进行判断 不然有可能出现undefined角undefined分的情况
if (!/^(-)?(0|[1-9]\d*)(.\d+)?$/.test(n))
return "数据非法";
标准的财务数字大写,如果是负数的话应该这么写:
比如-1.00
大写:(负数)壹元整
代码优化如下:
var head = n <0?'欠':'(负数)';
//对数字先进行判断不然有可能出现undefined角undefined分的情况
if(!/ ^( - )?(0 | [1-9] \ d *)(。\ d +)?$ / .test(n ))
返回“数据非法”;
var head = n <0?'欠':'(负数)';
这个优化的,好像也不对吧。如果是正数的话,是直接在前面加(负数)了啊。
不是应该
var head = n <0?'(负数)':'';
这样的吗?(如有不对,请指正。)
超出千亿的可以支持下吗
还会涉及到一个精度计算的问题
还会涉及到一个精度计算的问题
本来是写报销单的时候用的,没考虑这么多,请问精度问题会出现在哪些情况呢?
@volunteer1024 精度问题,依据 @hzq1988a 的方案改动后已经解决;
// 向右移位
function shiftRight(number, digit) {
digit = parseInt(digit, 10);
var value = number.toString().split('e');
return +(value[0] + 'e' + (value[1] ? +value[1] + digit : digit));
}
// 向左移位
function shiftLeft(number, digit) {
digit = parseInt(digit, 10);
var value = number.toString().split('e');
return +(value[0] + 'e' + (value[1] ? +value[1] - digit : -digit));
}
var digitUppercase = function (n) {
var fraction = ['角', '分'];
var digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
var unit = [
['元', '万', '亿'],
['', '拾', '佰', '仟'],
];
var head = n < 0 ? '欠' : '';
n = Math.abs(n);
var s = '';
for (var i = 0; i < fraction.length; i++) {
s += (digit[Math.floor(shiftRight(n, 1 + i)) % 10] + fraction[i]).replace(
/零./,
''
);
}
s = s || '整';
n = Math.floor(n);
for (var i = 0; i < unit[0].length && n > 0; i++) {
var p = '';
for (var j = 0; j < unit[1].length && n > 0; j++) {
p = digit[n % 10] + unit[1][j] + p;
n = Math.floor(shiftLeft(n, 1));
}
s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s;
}
return (
head +
s
.replace(/(零.)*零元/, '元')
.replace(/(零.)+/g, '零')
.replace(/^整$/, '零元整')
);
};
console.log(digitUppercase(30.01)); // > 叁拾元壹分
能否来一个单测,否则有些case很难覆盖
看看我的,测试用例在这里,这是参考税务局的实现,差异主要在 1.01
-> 壹元零壹分
:
/**
* 将阿拉伯数字价格转换为中文价格
* @param price 阿拉伯数字价格
* @returns 中文价格
*/
export function getChinesePrice(price: number) {
if (price === 0) return '零元整'
if (price >= 1e12) return '整数位已超过最大值'
const CHINESE_NUMBER_MAP = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
const CHINESE_UNIT_MAP = ['', '拾', '佰', '仟']
const CHINESE_BIG_UNIT_MAP = ['', '万', '亿']
const CHINESE_SMALL_UNIT_MAP = ['角', '分', '厘', '毫']
const priceStr = price.toString()
const priceArr = priceStr.split('.')
const integer = priceArr[0]
const decimal = priceArr[1]
let chineseIntegerPrice = ''
let zeroCount = 0
for (let i = 0; i < integer.length; i++) {
const num = +integer[i]
const unit = integer.length - i - 1 // 当前数字的单位
const quotient = Math.floor(unit / 4) // 1w为进位单位, 除 4 即为 万 亿
const remainder = unit % 4 // 1w为进位单位, 取模 4 即为 个 十 百 千
if (num === 0) {
zeroCount++
} else {
// 处理前置的零
if (zeroCount > 0) chineseIntegerPrice += CHINESE_NUMBER_MAP[0]
zeroCount = 0
chineseIntegerPrice += CHINESE_NUMBER_MAP[num] + CHINESE_UNIT_MAP[remainder]
}
if (remainder === 0 && zeroCount < 4) {
chineseIntegerPrice += CHINESE_BIG_UNIT_MAP[quotient]
}
}
// 价格为小数时,整数部分不显示
if (price < 1) chineseIntegerPrice = ''
else chineseIntegerPrice += '元'
let chineseDecimalPrice = ''
if (!decimal) {
chineseDecimalPrice = '整'
} else {
let hasZero = false
for (let i = 0; i < decimal.length; i++) {
const num = +decimal[i]
if (num) chineseDecimalPrice += CHINESE_NUMBER_MAP[num] + CHINESE_SMALL_UNIT_MAP[i]
else hasZero = true
}
if (chineseIntegerPrice && hasZero) chineseIntegerPrice += '零'
}
return chineseIntegerPrice + chineseDecimalPrice
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
做了一个移位的优化,防止出现精度不准的问题