#java #bigdecimal
Вопрос:
Я нахожусь в процессе создания приложения для преобразования базы чисел.
Я застрял на том, как преобразовать дробную часть в десятичную перед преобразованием в целевую базу.
Например:
Пользователь выбирает from base 16
to base 20
.
Число в base 16
= ab.375
Расчет, который я пытаюсь закодировать для этого конкретного примера, таков:
Base 16 to decimal calculation:
(ab.375)16 = (10 × 16 ^ 1) (11 × 16 ^ 0) (3 × 16 ^ -1) (7 × 16 ^ -2) (5 × 16 ^ -3) = (171.216064453125)10
У меня есть отдельный метод, который правильно выводит часть пользовательского ввода до десятичной точки. Моя проблема заключается в том, как учитывать дробную часть, и метод negative powers
since BigDecimal
pow
не может быть < 0
Вот мой convertToDecimalFraction
метод:
public static String convertToDecimalFraction(int sourceBase, String fraction) {
String[] fractionToConvertArray = ArrayUtilNoFraction.numberToArray(fraction);
int basePowers = -1;
BigDecimal integerToDecimalBig = BigDecimal.ZERO;
for (String s : fractionToConvertArray) {
integerToDecimalBig = integerToDecimalBig
.add(BigDecimal.valueOf(Integer.parseInt(s))
.multiply(BigDecimal.valueOf(sourceBase).pow(basePowers)));
basePowers = basePowers - 1;
}
return integerToDecimalBig.toString();
}
На случай, если вам интересно, вот мой ArrayUtilFraction.numberToArray
:
public static String[] numberToArray(String numberToConvert) {
String[] numberToConvertArray = String.valueOf(numberToConvert).split("");
String[] possibleValues = new String[]{
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z"
};
StringBuilder outputValues = new StringBuilder();
int count = 0;
for (String number : numberToConvertArray) {
for (String value : possibleValues) {
if (number.equalsIgnoreCase(value)) {
outputValues.append(count).append(" ");
break;
} else {
count = count 1;
}
}
count = 0;
}
return outputValues.toString().split(" ");
}
Комментарии:
1. x^-n = 1/(x^n) надеюсь, это поможет
Ответ №1:
Вот несколько советов.
- Нет необходимости постоянно использовать эту
pow
функцию. Рассмотрим базовое16
значение1EF.2DA
. - Мощность будет
3
, так как у вас есть три цифры слева отradixPoint
. Поскольку радиус будет16
таким, установите свой начальный делитель равным
divisor = BigDecimal.pow(16,3);
- Затем удалите десятичную точку из строки, давая
1EF2DA
. - Теперь, используя начальное значение
b = BigDecimal.ZERO
цикла, проведите цифры слева направо.charToBase10
является ли карта для перехода от исходного радиуса к base10 (напримерE to 14
)
b = b.add(BigDecimal.valueOf(charToBase10.get(digit))
.multiply(divisor));
divisor = divisor.divide(sourceRadix);
- Каждый раз, проходя через цикл,
b
создается так, чтобы содержать это число. Так как делитель в конечном итоге будет меньше, чем1
дробная часть, будет постепенно появляться.
И вот быстрый трюк для преобразования любого десятичного дробного значения в другое основание.
- предположим, вы хотели преобразовать .45(10) в базовый
2
. Выходные данные будут добавлены в биты.
2*.45 = 0.90 non-fraction portion is 0 so first bit is 0
2*.90 = 1.80 non-fraction portion is 1 so next bit is 1
2*.80 = 1.60 - next bit is 1
2*.60 = 1.20 - next bit is 1
2*.20 = 0.40 - next bit is 0
2*.40 = 0.80 - next bit is 0
2*.80 = 1.60 - next bit is 1 (and we have reached a repeating point)
So the answer is
bits = .0111001[10011001100110011....]
Это будет работать для любой базы, и вам понадобится карта, чтобы отобразить правильных персонажей. Вам также нужно будет определить, какую точность во всем процессе вы хотите сохранить.
Комментарии:
1. Спасибо вам за это. Я относительно новичок в Java, поэтому с нетерпением жду возможности в ближайшее время поделиться своим завершенным приложением для обзора кода SO. Я предпочитаю кодировать свои собственные методы вместо использования встроенных методов, например
charToBase10
, чтобы я мог узнать как можно больше. Пока речь идет не об оптимизации, а более или менее о понимании основ!2. Всегда пожалуйста! Просто, чтобы вы знали,
charToBase10
это не встроенный метод. Это экземпляр класса в API, который называетсяHashMap.
В этом отношении он ничем не отличается от использованияString
илиBigDecimal
которые также являются классами в API.