如何将REAL48 float转换为double [英] How to convert REAL48 float into a double

查看:316
本文介绍了如何将REAL48 float转换为double的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在连接到一个Pervasive SQL数据库,该数据库将一些数据分为两个字段.实际上,DOUBLE字段被分为fieldName_1和fieldName_2,其中_1是2字节整数,而_2是4字节整数.

I am connecting to a Pervasive SQL database which splits some data over two fields. DOUBLE fields are actually split into fieldName_1 and fieldName_2 where _1 is a 2 byte int and _2 is a 4 byte int.

我想获取这些值并将其使用PHP转换为可用值. 我有一些示例代码可以进行转换,但是它是用Delphi编写的,我不理解:

I want to take these values and convert them using PHP into a usable value. I have some example code to do the conversion, but it is written in Delphi which I do not understand:

{ Reconstitutes a SmallInt and LongInt that form }
{ a Real into a double.                          }
Function EntConvertInts (Const Int2 : SmallInt;
                         Const Int4 : LongInt) : Double; StdCall;
Var
  TheRealArray : Array [1..6] Of Char;
  TheReal      : Real;
Begin
  Move (Int2, TheRealArray[1], 2);
  Move (Int4, TheRealArray[3], 4);
  Move (TheRealArray[1], TheReal, 6);

  Result := TheReal;
End;

某些数据[fieldName_1,fieldName_2]

Some data [fieldName_1,fieldName_2]

[132,805306368]->这应该是11

[132, 805306368] -> this should be 11

[132,1073741824]->这应该是12

[132, 1073741824] -> this should be 12

我对逻辑的理解不足,无法将其移植到PHP中.非常感激任何的帮助.谢谢

I don't understand the logic enough to be able to port this into PHP. Any help would be most appreciated. Thanks

编辑. 这是他们提供的C代码,显示了符号/指数:

EDIT. This is the C code that they provided, showing sign/exponent:

double real_to_double (real r)
/* takes Pascal real, return C double */
{
    union doublearray da;
    unsigned x;

    x = r[0] & 0x00FF;  /* Real biased exponent in x */
    /* when exponent is 0, value is 0.0 */
    if (x == 0)
        da.d = 0.0;
    else {
        da.a[3] = ((x + 894) << 4) |  /* adjust exponent bias */
                  (r[2] & 0x8000) |  /* sign bit */
                  ((r[2] & 0x7800) >> 11);  /* begin significand */
        da.a[2] = (r[2] << 5) |  /* continue shifting significand */
                  (r[1] >> 11);
        da.a[1] = (r[1] << 5) |
                  (r[0] >> 11);
        da.a[0] = (r[0] & 0xFF00) << 5; /* mask real's exponent */
    }
    return da.d;
}

推荐答案

将其添加为另一个答案,因为我终于弄清楚了.这是将转换值的PHP代码.它必须手动计算,因为PHP不知道如何解压缩Real48(非标准).在下面的注释中进行解释.

Adding this as another answer because I've finally figured this out. Here is PHP code which will convert the values. It has to be manually calculated because PHP does not know how to unpack a Real48 (non standard). Explanation in comments below.

function BiIntToReal48($f1, $f2){
  $x = str_pad(decbin($f1), 16, "0", STR_PAD_LEFT);
  $y = str_pad(decbin($f2), 32, "0", STR_PAD_LEFT);
  //full Real48 binary string
  $real48 = $y . $x;

  //Real48 format is V = (-1)^s * 1.f * 2^(exp-129)
  // rightmost eight bits are the exponent  (bits 40-->47)
  // subtract 129 to get the final value
  $exp = (bindec(substr($real48, -8)) - 129);

  //Sign bit is leftmost bit (bit[0])
  $sign =$real48[0];

  //Now work through the significand - bits are fractional binary 
  //(1/2s place, 1/4s place, 1/8ths place, etc)
  // bits 1-->39 
  // significand is always 1.fffffffff... etc so start with 1.0
  $sgf = "1.0";

  for ($i = 1; $i <= 39; $i++){
      if ($real48[$i] == 1){
        $sgf = $sgf + pow(2,-$i); 
      }       
  } 
  //final calculation
  $final = pow(-1, $sign) * $sgf * pow(2,$exp);
  return($final);
}
$field_1 = 132;
$field_2 = 805306368;      
$ConvVal = BiIntToReal48($field_1, $field_2);
// ^ gives $ConvVal = 11, qed

这篇关于如何将REAL48 float转换为double的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆