我的任务是创建一个递归方法makeDecimal,当传递一个数字(由String表示)及其基数时,将该数字转换为基数10.您将需要使用方法Integer.parseInt(str)
。 (提示:使用子字符串。)此方法采用String
并返回其整数形式。
例如,Integer.parseInt("21");
将返回int 21。
以下是makeDecimal如何工作的一些示例:
makeDecimal("11", 2)
将返回3.
makeDecimal("100", 4)
将返回16。
这是我的尝试:
public static double makeDecimal(String number, int base){
int len = number.length();
double f = 0;
if(len <= 0)
return 0;
else{
makeDecimal(number,base);
double temp = Integer.parseInt(number.substring(len - 1, len + 1));
f = f + temp * Math.pow(3, len-1);
}
len--;
return f;
}
但是,我收到“溢出错误”,我不知道它是否写得正确。
答案 0 :(得分:7)
您正在使用与传入的完全相同的参数进行递归。因此,调用本身会以相同的方式递归,直到堆栈溢出。这不是递归应该如何工作的。相反,您需要弄清楚如何在当前调用中执行一个问题,然后递归以执行较小的问题。
在您的代码中,它甚至不清楚您使用的是什么逻辑。 (计算3 len
- 1 的重点是什么?)试试这个:
base
倍于的所有值,但不包括输入的最后一位数。 (提示:这是一个使用递归的好地方。)您应该能够将该描述转换为适当的方法调用并使用substring()
。
哦,另外一件事:这里没有理由使用double
值。只需坚持int
变量。你不会需要Math.pow()
。
答案 1 :(得分:3)
这是使用递归substring
和Integer.parseInt
的最简单的解决方案:
public int makeDecimal(String value, int base) {
// exit from recursion
if (value.length() < 1)
return 0;
//parsing last character of string
int charValue = Integer.parseInt(value.substring(value.length() - 1), base);
//calling recursion for string without last character
return makeDecimal(value.substring(0, value.length() - 1), base) * base + charValue;
}
答案 2 :(得分:1)
编辑:起初我曾经说过,这个解决方案的递归是有义务的,所以我没有它的原始答案可以在下面四个。
以下是递归的解决方案,没有substring
和Math.pow
:
public double makeDecimal(String value, int base) {
makeDecimal(value, base, value.length() - 1);
}
public double makeDecimal(String value, int base, int index) {
double result = 0;
if (index < 0)
return result;
double charValue = 0;
char currentChar = values.get(Character.toUpperCase(value.charAt(index));
if (currentChar >= 0 && currentChar <= '9') {
charValue = currentChar - '0';
} else if (currentChar >= 'A' && currentChar <= 'Z') {
charValue = currentChar - 'A';
} else {
throw new InvalidValueException("Unsupported character '" + currentChar + "'.");
}
if (charValue >= base) {
throw new InvalidValueException("Wrong character '" + currentChar + "' for base '" base + "'.");
}
return makeDecimal(value, base, index - 1)) * base + charValue;
}
原始答案:这样的事情适用于从2到36岁的任何基地:
private Map<Character, Integer> getCharValues(int base)
{
Map<Character, Integer> values = new HashMap<Character, Integer>();
for (int i = 0; i < base; i++){
if (i < 10) {
values.put('0' + i, i);
} else if (i < 36) {
values.put('A' + i - 10, i);
} else {
throw new InvalidValueException("Base '" + base + "' not supported");
}
}
return values;
}
public double makeDecimal(String value, int base)
{
Map<Character, Integer> charValues = getCharValues(base);
double result = 0;
for (int i = 0; i < value.length(); i++){
result = result * base + charValues.get(Character.toUpperCase(Character.toUpperCase(value.charAt(i))));
}
return result;
}
如果你需要超过36的基数,你可以扩展方法getCharValues
中的字符集。另外,最好不要每次创建HasMap
,只是将它存储为最大基数,如果char值超过给定的基数则抛出异常。
答案 3 :(得分:1)
这是我用Python编写原型后的解决方案(如果您有兴趣,我也可以包含Python源代码):
import java.util.HashMap;
import java.util.Map;
public class MakeDecimal {
public static final Map<Character, Integer> alphabet = buildAlphabetTable();
public static void main(String[] args) {
// System.out.println(alphabet);
System.out.println(makeDecimal("af10bb1", 16));
}
// pos refers to the position of the character in the string.
// For example, if you have the following binary string 100
// then 1 at the left is at position 2,
// the 0 in the middle is at position 1,
// and the right most 0 is at position 0
// (you start counting from the right side).
// In general, you would convert that string in the following way:
// 2^2 * 1 + 2^1 * 0 + 2^0 * 0 = 4
// If the base was n, then you would have
// first * n^{pos + "length of string - 1"} + ... + penultimate * n^{pos + 1} + last * n^{pos}
// Note that pos starts from 0.
private static int makeDecimal(String s, int base, int pos) {
if (s.length() == 0) {
return 0;
} else {
int last = (int) Math.pow(base, pos) * alphabet.get(s.charAt(s.length() - 1));
return makeDecimal(s.substring(0, s.length() - 1), base, pos + 1) + last;
}
}
public static int makeDecimal(String s, int base) {
if (s.length() == 0) {
return 0;
}
if (base < 2 || base > 36) {
throw new IllegalArgumentException("not base >= 2 and base <= 36");
}
return makeDecimal(s.toLowerCase(), base, 0);
}
// Creates a table that maps characters to their decimal value
// the characters can be also '0' or '2' (or any other character number)
// or they can be a character of the English alphabet
private static Map<Character, Integer> buildAlphabetTable() {
Map<Character, Integer> a = new HashMap<>(36);
int i = 0;
for (char c = '0'; c <= '9'; c++, i++) {
a.put(c, i);
}
for (char c = 'a'; c <= 'z'; c++, i++) {
a.put(c, i);
}
return a;
}
}
我的解决方案基于以下帖子,您应该阅读以便更新如何在基数之间进行转换的想法。
它不接受小于2或大于36的基数。当你以大写字母传递英文字符时它也会处理。