2010-05-21 54 views
4

我正在使用TStream來讀取二進制數據(感謝這篇文章:How to use a TFileStream to read 2D matrices into dynamic array?)。如何轉換Big Endian以及如何翻轉最高位?

我的下一個問題是數據是Big Endian。從我的閱讀中,Swap()方法似乎被棄用。我將如何交換下面的類型?

16-bit two's complement binary integer 
32-bit two's complement binary integer 
64-bit two's complement binary integer 
IEEE single precision floating-point - Are IEEE affected by Big Endian? 

最後,因爲數據是無符號的,該數據集的創造者所儲存的無符號值作爲符號整數(不包括IEEE)。他們指示只需要添加偏移量(2^15,2^31和2^63)來恢復未簽名的數據。但是,他們指出,翻轉最重要的位是最快的方法。如何有效地翻轉16,32或64位整數的最高有效位?

所以,如果在磁盤上(16位)的數據是「85 FB」 - 讀取數據和交換和位翻轉將是1531

後所期望的結果是否有辦法來完成交換並有點翻轉泛型,所以它適合上面鏈接的通用答案?

是的,孩子們,這是NASA,ESO和所有專業天文學家如何存儲科學的天文數據。這個FITS標準被有些人認爲是它在擴散和靈活性方面創造的最成功的標準之一!

+0

...什麼?你是如何得到1531而不是7b85的? – 2010-05-21 13:46:34

+0

是的,我也得到了7B 85,其中十進制是31621. – 2010-05-21 13:52:02

+0

1531 = $ 85FB xor $ 8000 – kludg 2010-05-21 14:05:52

回答

7

未測試:

function Flip16(const Value: Word): Word; inline; 
begin 
    Result:= Value xor $8000; 
end; 

function Flip32(const Value: LongWord): LongWord; inline; 
begin 
    Result:= Value xor $80000000; 
end; 

function Flip64(const Value: UInt64): UInt64; inline; 
begin 
    Result:= Value xor $8000000000000000; 
end; 

function SwapBytes(Value: LongWord): Single; 
type 
    Bytes = packed array[0..3] of Byte; 

begin 
    Bytes(Result)[0]:= Bytes(Value)[3]; 
    Bytes(Result)[1]:= Bytes(Value)[2]; 
    Bytes(Result)[2]:= Bytes(Value)[1]; 
    Bytes(Result)[3]:= Bytes(Value)[0]; 
end; 

更新:那麼,如果你要優化:)

function SwapBytes(Value: LongWord): Single; register; 
asm 
    BSWAP EAX 
end; 

更新一次更

SO中的常見做法是每個帖子都有一個問題 - 它通常會帶來更好的答案。

1)IEEE是否受Big Endian影響?

是的,浮點值可以是Big Endians,但這並不意味着您的浮點值是Big Endians - 請檢查您的文檔。

2)翻轉最顯著位 - 答案已經給出,但因爲你可能有大Endians,你可能只需要翻轉最顯著位在至少顯著字節,即只是xor $ 80;

3)將big endian轉換爲little endian;

對於16位值使用交換功能 - 很難理解爲什麼delphi幫助說這個函數只是爲了向後兼容; Remko注意到也可以使用XCHG asm指令;

對於32位值,您可以在Marco的評論中使用我的代碼或代碼;

爲64位值,你可以使用的馬可像這樣的代碼修改:

function Swap64(Value: UInt64): UInt64; 
begin 
    Result:= Swap32(LongWord(Value)); 
    Result:= (Result shl 32) or Swap32(LongWord(Value shr 32)); 
end; 

4)是否有可能在這裏使用泛型?

我不認爲這是一個好主意。

+0

swap(word(value))shl 16 + swap(word(value shr 16)); – 2010-05-21 14:08:42

+0

bswap eax交換DWORD,交換WORD使用xchg al,啊 – Remko 2010-05-21 14:56:52

+2

@ user246408 - 誰是'swap32'?它是在Delphi中定義的嗎? – Ampere 2015-10-18 11:31:48

0

那麼,我不太瞭解字節交換,但翻轉一個位很容易。用一個二進制表示全部爲0的掩碼異或你的值,除了你想要翻轉的位爲1。如果你想得到最高有效位,以十六進制表示,單個字節爲$80,對於一個單詞爲$8000,對於一個雙字,你猜對了,$80000000

+0

而對於64位無符號? : - ) – 2010-05-21 13:49:58

+0

在32位版本的末尾添加另外8個零。 :P – 2010-05-21 13:57:18

+0

嗯,是的,似乎接受無符號的十六進制值。如果算術運作,我將在今晚進行測試。 (FPC有一個無符號的64位類型,QWORD delphi沒有) – 2010-05-21 14:06:46

相關問題