將8個內存字節轉爲浮點數(Double)

{
函數功能:將8個內存字節(低位在前,高位在後)轉爲浮點數 Double
創建人:skyjacker
網址:Http://blog.csdn.net/skyjacker
Email:hemiaoyu At gmail.com
創建日期:2007-01-12
函數根據:IEEE標準754(4個內存字節轉爲Single同理)
雙精度:N共32位,其中S佔1位,E佔11位,M佔52位。
公式:n=(-1)^s * 2^e * m
}
function ByteToFloat(const Bytes: TByte8): Double;
const
  k = 11; //冪位數 Double=11
var
  TmpByte: Byte; //臨時字節

  //公式相關
  n: Double; //結果
  s: Integer; //符號位數字表示 +1 -1
  e: Integer; //冪值
  m: Double; //位數值

  //規格化
  bias: Integer; //偏置
  En: Integer; //冪的值

  I: Integer; //位數 m 23位
  A: Integer; //3~8個字節
  B: Integer; //TBits偏移 從5開始
  Bits: TBits; //存放二進制位 E=11 M=52

  //判斷是否規格化
  function NormalizedStatus(const Bits: TBits): Byte;
  var
    I: Integer;
    a, b: Integer;
  begin
    a := 0;
    b := 0;
    for I := 11 downto 1 do //Error:for I:=Bits.size(=12) downto 1 do
    begin
      if Bits.Bits[I] then
        Inc(b)
      else
        Inc(a);
    end;
    if (Bits.Size - 1) = a then //Bits.Size大小變爲12
      Result := $00
    else if (Bits.Size - 1) = b then
      Result := $FF
    else Result := $01; //規格化
  end;
begin

  //符號相關
  if (Bytes[1] and $80) = $00 then
    s := 1
  else
    s := -1;

  bias := pow(2, (k - 1)) - 1;

  //整理11位二進制冪值 E
  Bits := TBits.Create;
  Bits.Size := 11;
  TmpByte := Bytes[1];
  TmpByte := TmpByte shl 1; //移去符號位
  for I := 1 to 7 do
  begin
    Bits[I] := ((TmpByte and $80) = $80);
    TmpByte := TmpByte shl 1;
  end;

  TmpByte := Bytes[2];
  for I := 1 to 4 do
  begin
    Bits[I + 7] := ((TmpByte and $80) = $80);
    TmpByte := TmpByte shl 1;
  end;
  //求冪值
  En := 0;
  for I := 11 downto 1 do
  begin
    if Bits.Bits[12 - I] then
      En := En + pow(2, (I - 1));
  end;

  TmpByte := NormalizedStatus(Bits);
  //是否規格化判斷
  if TmpByte = $00 then
  begin
    e := 1 - bias;
    m := 0; //m的初始值 非規格化
  end
  else if TmpByte = $FF then
  begin
    //特殊數值: 當E的二進制位全爲1時爲特殊數值。
    Result := 0; //防止溢出或未初始化
    Exit;
  end
  else
  begin //規格化計算方法
    e := En - bias;
    m := 1; //m的初始值 規格化
  end;

  //整理52位尾數二進制M
  Bits.Size := 52; //Size自動復值了以前11個值,由於重新賦值,因爲不會影響結果。
  TmpByte := Bytes[2]; //5~8 bit
  TmpByte := TmpByte shl 4;
  for I := 1 to 4 do
  begin
    Bits[I] := ((TmpByte and $80) = $80);
    TmpByte := TmpByte shl 1;
  end;

  //3到8個字節位存入Bits
  B := 5;
  for A := 3 to 8 do
  begin
    TmpByte := Bytes[A];
    for I := 1 to 8 do
    begin
      Bits[B] := ((TmpByte and $80) = $80);
      TmpByte := TmpByte shl 1;
      Inc(B);
    end;
  end;

  //求m值
  for I := 1 to 52 do
  begin
    if Bits.Bits[I] then
      m := m + 1 / power(2, I);
  end;

  n := s * Power(2, e) * m;

  Bits.Free;

  Result := n;
end;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章