Я пытаюсь преобразовать число с плавающей запятой в упакованное десятичное число, но самое близкое решение, которое я нашел, это Гилберт Ле Бланк из этого поста: Java: преобразование строки в упакованное десятичное число
Это решение было скопированои сотни раз вставляется по всему переполнению стека, но оно глубоко испорчено:
public class PackedDecimal {
public static byte[] format(long number, int bytes) {
byte[] b = new byte[bytes];
final byte minusSign = 0x0D; // Minus
final byte noSign = 0x0F; // Unsigned
String s = Long.toString(number);
int length = s.length();
boolean isNegative = false;
if (s.charAt(0) == '-') {
isNegative = true;
s = s.substring(1);
length--;
}
int extraBytes = length - bytes + 1;
if (extraBytes < 0) {
// Pad extra byte positions with zero
for (int i = 0; i < -extraBytes; i++) {
b[i] = 0x00;
}
} else if (extraBytes > 0) {
// Truncate the high order digits of the number to fit
s = s.substring(extraBytes);
length -= extraBytes;
extraBytes = 0;
}
// Translate the string digits into bytes
for (int i = 0; i < length; i++) {
String digit = s.substring(i, i + 1);
b[i - extraBytes] = Byte.valueOf(digit);
}
// Add the sign byte
if (isNegative) {
b[bytes - 1] = minusSign;
} else {
b[bytes - 1] = noSign;
}
return b;
}
public static void main(String[] args) {
long number = -456L;
byte[] b = PackedDecimal.format(number, 5);
System.out.println("Number: " + number + ", packed: " + byteToString(b));
number = 0L;
b = PackedDecimal.format(number, 5);
System.out.println("Number: " + number + ", packed: " + byteToString(b));
number = 5823L;
b = PackedDecimal.format(number, 5);
System.out.println("Number: " + number + ", packed: " + byteToString(b));
number = 123456L;
b = PackedDecimal.format(number, 5);
System.out.println("Number: " + number + ", packed: " + byteToString(b));
}
public static String byteToString(byte[] b) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < b.length; i++) {
sb.append("0x");
sb.append(Integer.toHexString((int) b[i]).toUpperCase());
sb.append(" ");
}
return sb.toString();
}
}
И вот результаты теста.
Number: -456, packed: 0x0 0x4 0x5 0x6 0xD
Number: 0, packed: 0x0 0x0 0x0 0x0 0xF
Number: 5823, packed: 0x5 0x8 0x2 0x3 0xF
Number: 123456, packed: 0x3 0x4 0x5 0x6 0xF
Проблема с этим кодом:
- он имеет дело только с int.двойные и большие десятичные числа также могут быть преобразованы в упакованные десятичные числа.
- каждая цифра представлена половиной байта, поэтому число цифр в упакованном десятичном числе всегда должно быть даже не нечетным.
- Из того, что яузнал, что в приложениях, запускаемых на языке COBOL, обычно есть переменная длины для каждого поля данных, которое преобразуется, и длина числа цифр после десятичной точки.Код имеет фиксированную длину 5 для каждого упакованного десятичного числа.
Количество полубайтов, используемых в упакованном десятичном числе, рассчитывается как длина + 1 + (1, если общее количество полубайтов нечетное)
Этокод игнорирует все это.
Вот несколько примеров упакованного десятичного преобразования (l=length, half of bytes used)(p=number of half of bytes used after decimal point)
:
(l=4)(p=0) +123 > 00123C (l=4)(p=0)-123 > 00123D
(l=4)(p=0)(Unsigned) 12345 > 12345F
(l=6)(p=2)(Unsigned) 12345.67 > 1234567F
(l=8)(p=2)(Unsigned) 12345.67 > 001234567F
(l=6)(p=3)(Unsigned) > 12345.67 > 2345670F
Есть предложения о том, как его улучшить?