php - 将 double 转换为 Pascal 6 字节(48 位)实数格式

标签 php binary precision turbo-pascal

我需要对遗留文件中包含的数据进行一些处理。为此,我需要从 PHP 读取和写入 Turbo Pascal 的 6 字节(48 位) float 。 Turbo Pascal 数据类型通常称为 real48 ( specs )。

我有以下 php 代码来读取格式:

/**
 * Convert Turbo Pascal 48-bit (6 byte) real to a PHP float
 * @param binary 48-bit real (in binary) to convert
 * @return float number
 */
function real48ToDouble($real48) {
    $byteArray = array_values( unpack('C*', $real48) );
    if ($byteArray[0] == 0) {
        return 0; // Zero exponent = 0
    }

    $exponent = $byteArray[0] - 129;    
    $mantissa = 0;

    for ($b = 1; $b <= 4; $b++) {
        $mantissa += $byteArray[$b];
        $mantissa /= 256;
    }
    $mantissa += ($byteArray[5] & 127);
    $mantissa /= 128;
    $mantissa += 1;

    if ($byteArray[5] & 128) { // Sign bit check
        $mantissa = -$mantissa;
    }
    return $mantissa * pow(2, $exponent);
}

( adapted from )

现在我需要做相反的事情:数据类型。


笔记: 我知道 answer对于将 C# double 转换为 Delphi Real48 的问题,但它看起来非常老套,我认为可能有一个更简洁的解决方案。而且我的机器本身不支持 64 位。

最佳答案

再看一遍,the method posted in the answer to Convert C# double to Delphi Real48清理得很好。

供将来引用:

/**
 * Convert a PHP number [Int|Float] to a Turbo Pascal 48-bit (6 byte) real byte representation
 * @param float number to convert
 * @return binary 48-bit real
 */
function doubleToReal48($double) {
    $byteArray = array_values( unpack('C*', pack('d', $double)) ); // 64 bit double as array of integers
    $real48 = array(0, 0, 0, 0, 0, 0);

    // Copy the negative flag
    $real48[5] |= ($byteArray[7] & 128);

    // Get the exponent
    $n = ($byteArray[7] & 127) << 4;
    $n |= ($byteArray[6] & 240) >> 4;

    if ($n == 0) { // Zero exponent = 0
        return pack('c6', $real48[0], $real48[1], $real48[2], $real48[3], $real48[4], $real48[5]);
    }

    $real48[0] = $n - 1023 + 129;

    // Copy the Mantissa
    $real48[5] |= (($byteArray[6] & 15) << 3); // Get the last 4 bits
    $real48[5] |= (($byteArray[5] & 224) >> 5); // Get the first 3 bits
    for ($b = 4; $b >= 1; $b--) {
        $real48[$b] = (($byteArray[$b+1] & 31) << 3); // Get the last 5 bits
        $real48[$b] |= (($byteArray[$b] & 224) >> 5); // Get the first 3 bits
    }

    return pack('c6', $real48[0], $real48[1], $real48[2], $real48[3], $real48[4], $real48[5]);
}

关于php - 将 double 转换为 Pascal 6 字节(48 位)实数格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31940355/

相关文章:

php - 如何让 PHP 文件解析一些数据,而无需用户停留在页面上

c++ - 如何 'cout' double 值的正确小数位数?

c - 为什么 BLAS dsyrk 比简单的 C 实现更精确?

php - Pootle 导出不正确的 PHP 数组文件

php - 在 MySQL 与 PHP 中执行函数

php - 如何在点php之后和之前分隔数组

ios - 使用 C++ 模板的二进制到 float 的转换在模拟器上运行但在设备上出错

c++ - 二进制-十进制负位集

python - python中二进制文件的异或加密

python - Tensorflow 添加 float 给出额外的数字