2017-08-04 42 views
0

我有一個4 unsigned int條目具有相同的值的數組255我想將它們轉換爲decimal值。下面是代碼:小數構造函數拋出System.ArgumentException當我傳遞int數組4個元素

public static decimal BytesToDecimal(byte[] buffer, int offset = 0) 
{ 
    var decimalBits = new int[4]; 

    decimalBits[0] = buffer[offset + 0] | (buffer[offset + 1] << 8) | (buffer[offset + 2] << 16) | (buffer[offset + 3] << 24); 
    decimalBits[1] = buffer[offset + 4] | (buffer[offset + 5] << 8) | (buffer[offset + 6] << 16) | (buffer[offset + 7] << 24); 
    decimalBits[2] = buffer[offset + 8] | (buffer[offset + 9] << 8) | (buffer[offset + 10] << 16) | (buffer[offset + 11] << 24); 
    decimalBits[3] = buffer[offset + 12] | (buffer[offset + 13] << 8) | (buffer[offset + 14] << 16) | (buffer[offset + 15] << 24); 

    return new decimal(decimalBits); 
} 

static void Main(string[] args) 
{   
    decimal dd = BytesToDecimal(new byte[16] { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }); 
    Console.WriteLine("{0}", dd.ToString());   
} 

我期待的結果-1;但是,該程序引發以下異常。

未處理的異常信息:System.ArgumentException:十進制字節數組 構造需要含有VAL ID小數 字節長度爲4的陣列。

+0

本部分是否包含任何跨平臺的代碼?據我所知,'System.Decimal'的內部表示是不可移植的。 – Dai

回答

2

根據the constructor documentation for decimal,第四個int數組元素的位0到15以及24到30必須都是零。 255,作爲一個8位二進制數,全是1。因此,您需要爲構造函數設置一個每個位均設置爲1的整數數組。

+0

您不能將任意int數組傳遞給此構造函數,它用於decimal.GetBits方法的輸出。如果你想傳入你自己的int數組,你必須閱讀小數類型的文檔並理解它如何編碼它的數據。這不是一個簡單的指數,然後是加法算法。 –

0

您的錯誤是在假設您設置了小數點的所有位後,結果爲-1。這不是小數點存儲的方式。

您的方法對於整數是正確的,但對於像小數點這樣的固定點數不適用。小數點不僅存儲基數(尾數),而且還存儲小數點的位置。此外,由於尾數未經簽名,因此該符號的設置不同於十進制。

檢查this Q&A瞭解如何格式化小數的更多信息。

0

根據文檔Decimal(Int32[])將最後一個數組元素用作標誌。

比特2包含比例因子和符號,並且由以下部分組成:

0〜15位,低位字,未使用和必須爲零。

位16到23必須包含一個0到28之間的指數,它表示10的冪除以整數。

位24到30未使用且必須爲零。

位31包含符號; 0意味着積極,1意味着消極。以二進制格式Convert.ToString(-1, 2);

整數值-1等於

而這個值不匹配

private const int SignMask = unchecked((int)0x80000000); 

private const int ScaleMask = 0x00FF0000; 

口罩,這就是爲什麼在source code當你傳遞-1,條件

(f & ~(SignMask | ScaleMask)) == 0 && (f & ScaleMask) <= (28 << 16)) 

回報和下一個命令拋出異常。


更新,如果你想了解如何值爲-1十進制表示你可以使用Decimal.GetBits方法

string.Join(" ", decimal.GetBits((decimal) -1)) 

結果將是

1 0 0 -2147483648

.netFiddle