[英]C# Weird division issue
我有一種int和一種uint類型:
int tempA = 0xbc000669;
uint tempB = 0xbc000669;
當我做
tempA /0x2000
,想向右移動13,它給我0xfffde001
而
tempB / 0x2000
,也想向右移動13,它給了我正確的答案: 0x0005e000
有人知道為什么簽名后我得到一個錯誤的答案嗎? 我沒想到分裂會溢出嗎? 謝謝
在聲明中
tempA / 0x2000
編譯器會看到int類型的變量和數字文字值。 由於對int類型的除法需要兩個int類型的操作數,因此值0x2000也會自動轉換為int。 該語句評估為
(int)0xbc000669 / (int)0x2000
這是-1140849047 / 8192等於-139263
十六進制的-139263是FFFDE001(至少在32位值上)
實際上0xbc000669
不能包含在一個int
,更確切的說它代表一個negative integer
。 我們知道一個int
使用第32nd bit
作為sign bit
。 而0cbc000669
有最顯著半字節為0xb
其等於1011
- >的32nd bit
是1
,實際是一個負整數。 所以:
int tempA = 0xbc000669;
將使tempA
等於-1140849047
,將此數字右移13個二進制數字將返回獲得的准確結果: 0xfffde001
。
如果您像這樣將tempB
聲明為uint
:
uint tempB = 0xbc000669;
它可以完全包含在uint
因為uint
不使用第32nd bit
作為符號位。 實際數字是一個positive integer
,其值是3154118249
,將該值右移13個二進制數將得到准確的結果為0x5e000
從規范中關於整數除法的內容來看:
除法將結果舍入為零,結果的絕對值是最大可能的整數,該整數小於兩個操作數的商的絕對值。 當兩個操作數具有相同的符號時,結果為零或正;而當兩個操作數具有相反的符號時,結果為零或負。
如果我正確地解釋了該文本,則會導致以下情況:在第一個示例中,帶符號的int值設置了符號位; 第二個數字(0x2000)為正,因此結果為零或負。
解釋此問題的最佳方法是顯示位如何工作。 Wikipedia上有關簽名數字表示的文章對此進行了很好的介紹。 您將要閱讀關於二進制補碼的部分。
我認為期望是人們希望-1和1的二進制數相同,但-1的符號位為1。 不是這種情況。 1,例如
0000 0000 0000 0000 0000 0000 0000 0001
-1是
1111 1111 1111 1111 1111 1111 1111 1111
人們直覺上認為-1實際上是-127:
-127 == 1000 0000 0000 0000 0000 0000 0000 0001
現在,讓我們看看您得到的答案。 在有符號除法中,當您向右移動時,實際上實際上是將數字的左側填充1並加1。這就是您在結果中看到的結果。
0xFFFDE001 = 1111 1111 1111 1101 1110 0000 0000 0001
0x0005E000 = 0000 0000 0000 0101 1110 0000 0000 0000
您會注意到,它們都是一樣的,除了最上面的(來自已簽名部門的)左邊有13 1的填充,末尾有1的填充。
對於帶符號整數,要記住的重要一點是,二進制補碼會更改位的順序,因此,除符號位外,-50不具有與+50相同的位模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.