求JavaScript实现密集BCD转十进制函数(支持3位及以上数字)
密集BCD转十进制的JavaScript实现(反向工程版)
需求概述
现有一个将十进制转换为密集BCD(Packed BCD)的JavaScript函数dec_to_densely,需要对其进行反向工程,实现一个可将密集BCD转换为十进制的函数,要求支持3位及以上十进制数字的转换。
原十进制转密集BCD函数代码
function dec_to_densely(x, packed){ const holder = packed.split(""); let densely_packed = new Array(10); let merge = new Array(10000); if (x.length % 3 != 0) { if (x.length % 3 == 1){ for (let i = 0; i < 8; i++){ holder.unshift(0); } } else { for (let i = 0; i < 4; i++){ holder.unshift(0); } } } while (holder.length > 0) { densely_packed[5] = holder[7]; densely_packed[9] = holder[11]; //000 if (holder[0] == '0' && holder[4] == '0' && holder[8] == '0') { for (let i = 0; i < 3; i++){ densely_packed[i] = holder[i + 1]; } for (let i = 3; i < 5; i++){ densely_packed[i] = holder[i + 2]; } densely_packed[6] = '0'; for (let i = 7; i < 10; i++){ densely_packed[i] = holder[i + 2]; } } //001 else if (holder[0] == '0' && holder[4] == '0' && holder[8] == '1') { for (let i = 0; i < 3; i++){ densely_packed[i] = holder[i + 1]; } for (let i = 3; i < 5; i++){ densely_packed[i] = holder[i + 2]; } densely_packed[6] = '1'; densely_packed[7] = '0'; densely_packed[8] = '0'; } //010 else if (holder[0] == '0' && holder[4] == '1' && holder[8] == '0') { for (let i = 0; i < 3; i++){ densely_packed[i] = holder[i + 1]; } densely_packed[3] = holder[9]; densely_packed[4] = holder[10]; densely_packed[6] = '1'; densely_packed[7] = '0'; densely_packed[8] = '1'; } //011 else if (holder[0] == '0' && holder[4] == '1' && holder[8] == '1') { for (let i = 0; i < 3; i++){ densely_packed[i] = holder[i + 1]; } densely_packed[3] = '1'; densely_packed[4] = '0'; densely_packed[6] = '1'; densely_packed[7] = '1'; densely_packed[8] = '1'; } //100 else if (holder[0] == '1' && holder[4] == '0' && holder[8] == '0') { densely_packed[0] = holder[9]; densely_packed[1] = holder[10]; densely_packed[2] = holder[3]; densely_packed[3] = holder[5]; densely_packed[4] = holder[6]; densely_packed[6] = '1'; densely_packed[7] = '1'; densely_packed[8] = '0'; } //101 else if (holder[0] == '1' && holder[4] == '0' && holder[8] == '1') { densely_packed[0] = holder[5]; densely_packed[1] = holder[6]; densely_packed[2] = holder[3]; densely_packed[3] = '0'; densely_packed[4] = '1'; densely_packed[6] = '1'; densely_packed[7] = '1'; densely_packed[8] = '1'; } //110 else if (holder[0] == '1' && holder[4] == '1' && holder[8] == '0') { densely_packed[0] = holder[9]; densely_packed[1] = holder[10]; densely_packed[2] = holder[3]; densely_packed[3] = '0'; densely_packed[4] = '0'; densely_packed[6] = '1'; densely_packed[7] = '1'; densely_packed[8] = '1'; } //111 else if (holder[0] == '1' && holder[4] == '1' && holder[8] == '1') { densely_packed[0] = '0'; densely_packed[1] = '0'; densely_packed[2] = holder[3]; densely_packed[3] = '1'; densely_packed[4] = '1'; densely_packed[6] = '1'; densely_packed[7] = '1'; densely_packed[8] = '1'; } merge = merge.concat(densely_packed); for (let i = 0; i < 12; i++){ holder.shift() } } let dpacked = merge.join(""); return packed; }
反向实现:密集BCD转十进制函数
function densely_to_dec(denselyPackedStr, originalDecLength) { // 按每10位拆分密集BCD(原函数每组生成10位) const chunks = []; let temp = denselyPackedStr.split(''); while (temp.length > 0) { chunks.push(temp.splice(0, 10)); } let unpacked = []; // 反向处理每个10位的密集BCD块 chunks.forEach(chunk => { const holder = new Array(12); holder[7] = chunk[5]; holder[11] = chunk[9]; // 根据原函数的8种分支反向推导原始holder值 switch (`${chunk[6]}${chunk[7]}${chunk[8]}`) { case '000': // 对应原函数000分支 for (let i = 0; i < 3; i++) holder[i+1] = chunk[i]; for (let i = 3; i <5; i++) holder[i+2] = chunk[i]; for (let i =7; i<10; i++) holder[i+2] = chunk[i]; holder[0] = '0'; holder[4] = '0'; holder[8] = '0'; break; case '100': // 对应原函数001分支 for (let i =0; i<3; i++) holder[i+1] = chunk[i]; for (let i=3; i<5; i++) holder[i+2] = chunk[i]; holder[0] = '0'; holder[4] = '0'; holder[8] = '1'; break; case '101': // 对应原函数010分支 for (let i=0; i<3; i++) holder[i+1] = chunk[i]; holder[9] = chunk[3]; holder[10] = chunk[4]; holder[0] = '0'; holder[4] = '1'; holder[8] = '0'; break; case '111': // 先判断是否是011分支 if (chunk[3] === '1' && chunk[4] === '0') { for (let i=0; i<3; i++) holder[i+1] = chunk[i]; holder[0] = '0'; holder[4] = '1'; holder[8] = '1'; } // 101分支 else if (chunk[3] === '0' && chunk[4] === '1') { holder[5] = chunk[0]; holder[6] = chunk[1]; holder[3] = chunk[2]; holder[0] = '1'; holder[4] = '0'; holder[8] = '1'; } // 110分支 else if (chunk[3] === '0' && chunk[4] === '0') { holder[9] = chunk[0]; holder[10] = chunk[1]; holder[3] = chunk[2]; holder[0] = '1'; holder[4] = '1'; holder[8] = '0'; } // 111分支 else if (chunk[3] === '1' && chunk[4] === '1') { holder[3] = chunk[2]; holder[0] = '1'; holder[4] = '1'; holder[8] = '1'; } break; case '110': // 对应原函数100分支 holder[9] = chunk[0]; holder[10] = chunk[1]; holder[3] = chunk[2]; holder[5] = chunk[3]; holder[6] = chunk[4]; holder[0] = '1'; holder[4] = '0'; holder[8] = '0'; break; } // 将holder中的有效位加入结果 unpacked = unpacked.concat(holder.filter(bit => bit !== undefined)); }); // 根据原始十进制长度去掉前导补的0 let leadingZerosToRemove = 0; if (originalDecLength %3 ===1) leadingZerosToRemove =8; else if (originalDecLength %3 ===2) leadingZerosToRemove =4; if (leadingZerosToRemove >0) { unpacked.splice(0, leadingZerosToRemove); } // 将BCD位转换为十进制数字(每4位对应一个十进制数) let decStr = ''; for (let i=0; i<unpacked.length; i+=4) { const bcdDigit = unpacked.slice(i, i+4).join(''); decStr += parseInt(bcdDigit, 2).toString(); } // 去掉可能的前导零(如果原始数没有前导零的话) return decStr.replace(/^0+/, '') || '0'; }
函数说明
- 分组处理:原函数每12位BCD生成10位密集BCD,反向函数先将输入的密集BCD按每10位拆分处理。
- 分支反向推导:根据原函数的8种分支条件(由标识位组合判断),反向推导出原始的BCD位数据。
- 去除补位零:原函数会根据十进制长度补前导零(1位补8个,2位补4个),反向函数需要根据原始十进制长度去掉这些补位零。
- BCD转十进制:将还原后的BCD数据按每4位一组转换为十进制数字,拼接成最终结果。
内容的提问来源于stack exchange,提问作者alxyzzles
相关产品推荐
相关产品推荐

