Delphi IEEE754 (80) binary to Java Bigdecimal

64 Views Asked by At

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

  1. Delphi bytes:

    [51, 51, 51215240114205, 29, 64]
    

    Java bytes:

    [52, 51, 51, 51, 51, -41, -16, 114, -51, 29, 64]
    
  2. How to parse these flows back into BigDecimal type

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;
}
2

There are 2 best solutions below

0
xinle shan On

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.

0
xinle shan On

I understand. If you have specific code in Delphi that you'd like assistance with or if you need further clarification or assistance in translating it to another language, feel free to share the code or specific portions of it. I'm here to help!