Delphi IEEE754 (80) 二进制到 Java Bigdecimal

问题描述 投票:0回答:1

我们有两个团队,Delphi 团队和 Java 团队。 Delphi基于Delphi 11中的

TExtended80Rec
,存储在sqlite数据库中,并保存为二进制流。我尝试过使用Java来解析流中的内容,发现了几个困难

  1. Delphi 字节:

    [51, 51, 51215240114205, 29, 64]
    

    Java 字节:

    [52, 51, 51, 51, 51, -41, -16, 114, -51, 29, 64]
    
  2. 如何将这些流解析回

    BigDecimal
    类型

我希望得到您的帮助

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;
}
java delphi bigdecimal ieee-754 extended-precision
1个回答
0
投票

符号位:符号位是通过将最后一个字节值与十六进制数 $80 进行比较来确定的。

指数:提取十六进制最后2个字节的十进制值。

尾数:以十六进制计算剩余字节的十进制值,并将其乘以2的63次方。

最终值通过以下公式获得:符号位 * 尾数 * 2^(指数 - 16383) / 2^63。另外,通过添加 0.0000001 来进行精度处理。然后将生成的数值格式化为排除小数点后的尾随零,包括连续的零对及其他零。

© www.soinside.com 2019 - 2024. All rights reserved.