We have two teams, the Delphi team and the Java team. Delphi is based on TExtended80Rec in Delphi 11, which is stored in the sqlite database and saved as a binary stream. I have tried using Java to parse the content in the stream and have found several difficulties
Delphi bytes:
[51, 51, 51215240114205, 29, 64]Java bytes:
[52, 51, 51, 51, 51, -41, -16, 114, -51, 29, 64]How to parse these flows back into
BigDecimaltype
I hope to receive your help
public static void main(String[] args) {
// 从 Delphi 11 中获取的 10 字节的 Extended 类型字节数组
byte[] delphiBytes = {52, 51, 51, 51, -41, -16, 114, -51, 29, 64};
// 解析 Delphi 11 Extended 类型为 Java double
BigDecimal parsedValue = parseDelphiExtended(delphiBytes);
// 打印结果
System.out.println("解析后的值: " + parsedValue);
}
private static BigDecimal parseDelphiExtended(byte[] delphiBytes) {
// 解析符号位
boolean isNegative = (delphiBytes[0] & 0x80) != 0;
// 解析指数位
short exponent = (short) (((delphiBytes[1] & 0xFF) << 8) | (delphiBytes[2] & 0xFF));
int adjustedExponent = exponent - 16383;
// 解析尾数位
BigDecimal fraction = calculateFraction(delphiBytes);
// 计算 BigDecimal 类型的值
BigDecimal parsedValue = BigDecimal.valueOf(Math.pow(-1, isNegative ? 1 : 0) * Math.pow(2, adjustedExponent) * fraction.doubleValue());
return parsedValue;
}
private static BigDecimal calculateFraction(byte[] delphiBytes) {
// 解析尾数位
long mantissa = 0;
for (int i = 3; i < delphiBytes.length; i++) {
mantissa = (mantissa << 8) | (delphiBytes[i] & 0xFF);
}
// 构建 BigDecimal 类型的尾数
BigDecimal fraction = new BigDecimal(mantissa).divide(BigDecimal.valueOf(2).pow(64));
return fraction;
}
Sign Bit: The sign bit is determined by comparing the last byte value with the hexadecimal number $80.
Exponent: Extract the decimal value of the last 2 bytes in hexadecimal.
Mantissa: Calculate the decimal value of the remaining bytes in hexadecimal and multiply it by 2 raised to the power of 63.
The final value is obtained by applying the following formula: Sign Bit * Mantissa * 2^(Exponent - 16383) / 2^63. Additionally, precision handling is performed by adding 0.0000001. The resulting numeric value is then formatted to exclude trailing zeros after the decimal point, including consecutive pairs of zeros and beyond.