36进制加法Java语言
三十六进制加法
题目
给两个字符串num1,num2,实现36进制的数字相加。
10进制加法,逢十进一,每个位数数字可以为0-9,最小为0,最大为9,共10种情况
36进制加法,逢36进一,每个位数数字可以为0-35,最小为0,最大为35,共36种情况,这36种情况为0-9 10种 a-z 26种
36进制通过0 - 9 和a - z表示每个位数字0 - 35的情况。
输入输出
输入 | 输出 |
---|---|
bca1 a053 | lcf4 |
zzzaa zz11 | 10zybb |
初步分析
十进制加法我们先对齐两个数字,然后从后到前计算每个位相加结果。
1.进位问题:对于0-9的数字我们可以直接相加然后逢10进一,但这里是0-z相加,该如何做?
我们可以先将0-z转换为0-35,然后逢36进1。
//根据字符转数字
public int toNumber(char c){
if(Character.isDigit(c)){
return c - '0';
}else{
return c - 'a' + 10;
}
}
2.两个数位数不同问题:十进制中,199+99 = 298,999+99 = 1098,所以我们这里该如何实现同时遍历两个不同位数数字从后向前遍历?
一种解决办法是将位数较少的那一个数字左边补零,例如999+99看做999+099。
//补零操作,str为目标字符串,n为需要补充0的个数
public String padWithZeros(String str, int n){
StringBuilder sb = new StringBuilder(str);
for(int i=0;i<n;i++){
sb.insert(0,'0');
}
return sb.toString();
}
3.十进制相加后得到的和如果需要进位,减10剩下的就是该位上的结果,但是36进制相加后如果需要进位,减36后可能还剩0-35,如何通过数字0-35得到最终36进制的表示结果0-z?
public static final String DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz";
public char getCharValue(int num){
//我们发现直接通过一个0-35之间的数字转化为0-z没有很好的工具,但是0-35正好一一对应0-z,所以考虑将0-z放入数组中,通过0-35下标去取。
return DIGITS.charAt(num);
}
我的思路
- 传入两个字符串,记录较长字符串的长度为n作为遍历次数,遍历到n - 较短字符串长度 + 1时证明断字符串已经遍历完了,剩下根据是否进位拼接较长字符串剩余部分。
- 存在的问题:倒着遍历字符串时,无法确定起始索引,因为两个字符串长度不同。
- 正确做法:先把字符串长度补齐
- 使用boolean变量标志是否进位发生,注意:每次进位只可能进1。
- 存在缺陷:每次需要判断boolean值,然后去确定两数相加是否要加进位的那个1
- 改进:使用int型变量
count
存储,每次计算两数和都加上count
- 后续改进:1.char值转为对应的0-35数字应该包装到一个方法中2.0-35数字转为36进制值应该包装到方法中。
题解思路
- 传入str1,str2取较长字符串长度n,通过
padWithZeros
方法补齐两个字符串 - 使用StringBuilder记录加法最终结果
- 记录是否有进位不选择
boolean
型而是选择int
型,方便进位计算 - 两个字符串长度一致后,从后向前遍历,每次遍历要做的事:1.将对应位置char值根据
toNumber
方法得到对应数字2.相加两个数字,小于36不进位,carry赋值为0,通过getCharValue
方法获取对应的36进制表示形式3.大于36进位,carry赋值为1,然后getCharValue
方法获取36进制表示形式4.注意相加两个数字时要加上carry - for循环结束后,如果carry>0代表还有进位发生,需要在结果字符串首部插入字符1。因为进位最多只可能进1位,不可能进2位。
- 最终返回sb
图示
代码
public class Add36 {
private static final String DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz";
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str1 = sc.nextLine();
String str2 = sc.nextLine();
System.out.println(getResult(str1, str2));
}
private static String getResult(String str1, String str2) {
int maxLength = Math.max(str1.length(), str2.length());
StringBuffer sb = new StringBuffer();
int carry = 0;
//补齐长度
str1 = padWithZeros(str1, maxLength);
str2 = padWithZeros(str2, maxLength);
for (int i = maxLength - 1; i >= 0; i--) {
char c1 = str1.charAt(i);char c2 = str2.charAt(i);
int digit1 = getDigitValue(c1);int digit2 = getDigitValue(c2);
int sum = digit1 + digit2 + carry;
carry = sum / 36;
int remainder = sum % 36;
sb.insert(0, getCharValue(remainder));
}
if (carry > 0){
sb.insert(0, getCharValue(carry));
}
return sb.toString();
}
private static char getCharValue(int remainder) {
return DIGITS.charAt(remainder);
}
private static int getDigitValue(char c) {
if (Character.isDigit(c)){
return Character.getNumericValue(c);
}else {
return c - 'a' + 10;
}
}
private static String padWithZeros(String str, int length) {
StringBuilder sb = new StringBuilder(str);
while (sb.length() < length){
sb.insert(0, '0');
}
return sb.toString();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!