进制转换函数问题:保留前导零的修复方案求助
解决进制转换中前导零丢失的问题
嘿,你遇到的这个问题其实很典型——你的进制转换函数本质是在处理数值,而不是带格式的数字字符串。从数值层面来说,"0001"和"1"是完全相等的十进制数,所以转换为3进制后都会得到"1",再转回十进制自然也只能得到"1"——函数根本没办法记住原字符串的前导零信息,因为这些零在数值转换中没有意义。
要解决这个问题,我们需要额外保留原字符串的格式长度信息,下面给你两种实用的解决方案:
方案一:手动记录原长度,解码后补前导零
如果你的场景中,原输入的位数是固定的(比如都是4位十进制),可以在转换时先记下原字符串的长度,解码完成后用padStart方法补零到原长度:
function convertBase(value, from_base, to_base) { var range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split(''); var from_range = range.slice(0, from_base); var to_range = range.slice(0, to_base); var dec_value = value.split('').reverse().reduce(function(carry, digit, index) { if (from_range.indexOf(digit) === -1) throw new Error('Invalid digit `' + digit + '` for base ' + from_base + '.'); return carry += from_range.indexOf(digit) * (Math.pow(from_base, index)); }, 0); var new_value = ''; while (dec_value > 0) { new_value = to_range[dec_value % to_base] + new_value; dec_value = (dec_value - (dec_value % to_base)) / to_base; } return new_value || '0'; } // 处理带前导零的示例 let raw = "0001" const originalLength = raw.length; // 记录原字符串的长度 document.body.innerHTML += "raw: " + raw + "<br>" let encoded = convertBase(raw, 10, 3) document.body.innerHTML += "encoded: " + encoded + "<br>" let decoded = convertBase(encoded, 3, 10) // 补前导零到原长度 decoded = decoded.padStart(originalLength, '0'); document.body.innerHTML += "decoded: " + decoded + "<br><br>"
方案二:修改函数,新增参数支持保留格式
如果需要更通用的处理,可以给函数加一个可选参数,让它在反向转换时指定目标长度,自动补全前导零:
function convertBase(value, from_base, to_base, targetLength = null) { var range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split(''); var from_range = range.slice(0, from_base); var to_range = range.slice(0, to_base); // 转换为十进制数值 var dec_value = value.split('').reverse().reduce(function(carry, digit, index) { if (from_range.indexOf(digit) === -1) throw new Error('Invalid digit `' + digit + '` for base ' + from_base + '.'); return carry += from_range.indexOf(digit) * (Math.pow(from_base, index)); }, 0); // 转换为目标进制字符串 var new_value = ''; if (dec_value === 0) { new_value = '0'; } else { while (dec_value > 0) { new_value = to_range[dec_value % to_base] + new_value; dec_value = Math.floor(dec_value / to_base); } } // 如果指定了目标长度,自动补前导零 if (targetLength !== null) { new_value = new_value.padStart(targetLength, '0'); } return new_value; } // 使用示例 let raw = "0001" document.body.innerHTML += "raw: " + raw + "<br>" // 十进制转3进制,无需指定长度(前导零在数值转换中无意义) let encoded = convertBase(raw, 10, 3) document.body.innerHTML += "encoded: " + encoded + "<br>" // 3进制转回十进制,指定目标长度为原字符串的长度 let decoded = convertBase(encoded, 3, 10, raw.length) document.body.innerHTML += "decoded: " + decoded + "<br><br>"
额外说明
- 前导零属于格式信息,不属于数值本身,所以单纯的进制转换函数无法自动保留它,必须手动传递这个长度信息。
- 如果原输入是全零字符串(比如
"0000"),上面的两种方案也能正确补回原格式。
内容的提问来源于stack exchange,提问作者user3596335
相关产品推荐
相关产品推荐

