位移运算的问题(100分)

  • 主题发起人 主题发起人 Miros
  • 开始时间 开始时间
M

Miros

Unregistered / Unconfirmed
GUEST, unregistred user!
program Project1;

{$APPTYPE CONSOLE}

uses
SysUtils;

var
W: Word;
B, G, R: Byte;

begin
{ TODO -oUser -cConsole Main : Insert code here }
W := 40000;
WriteLn('I: ' + IntToStr(W));
B := W Shr 11;
G := W Shl 5 Shr 10;
R := W Shl 11 Shr 11;
WriteLn('R: ' + IntToStr(R) + ',' + 'G: ' + IntToStr(G) + ',' + 'B: ' + IntToStr(B));
W := B Shl 11 + G Shl 5 + R;
WriteLn('I :' + IntToStr(W))
//为什么前后结果中W的值不同呢? 要怎么算呢?
ReadLn(W);
end.
//不好意思 刚才题目问得太含糊了
//我的目的是想知道如何运算 B , G , R 可以返回的W的值!
 
W 是2个Byte ,R、G、B是一个Byte ;

“B Shl 11 ”不知道是不是 0 ,你测试一下看了;

B, G, R: Word
看看;
 
w:1001110001000000
B := W Shr 11
w:0000000000010011
B:00010011
W Shl 5
w:0000001001100000
Shr 10
w:0000000000000000
 
to bmsr:
前面W值是不会改变的。

W := 40000
//W:1001110001000000
WriteLn('I: ' + IntToStr(W));
B := W Shr 11
//W:1001110001000000 B:10011;
G := W Shl 5 Shr 10
//W:1001110001000000 G:11100010
<<--- 问题在这两个运算里
R := W Shl 11 Shr 11
//W:1001110001000000 R:1000000 <<---
 
shl,shr进行移位计算时,会舍掉数据的。你当然不能指望进行这样的操作后,W Shl 11 Shr 11;W的值不变。
 
to 楼上:
如果W = 40000
则W 和 W shl 11 shr 11是相等的,因为移位运算时总位数并没有超出32位。

刚才看了下程序的算法:
1、因为定义时 B, G, R: Byte;所以在做完移位后取低8位作为要赋的值。
2、在移位时还是按照Integer类型即32位来做运算的。

B := W Shr 11
// W值不变:1001110001000000 B:10011;
G := W Shl 5 Shr 10
// W值不变:1001110001000000 G:对W先左移5再右移10再取低8位,为11100010
R := W Shl 11 Shr 11
// W值不变:1001110001000000 R:对W先左移11再右移11再取低8位,为1000000
W := B Shl 11 + G Shl 5 + R
//B左移11为1001100000000000;G左移5为1110001000000;R为1000000,W为3值相加1011010010000000(46208)与结果相符.

3、说明两点结果,在对W做移位操作再赋给别的值时,W值本身不会改变。
4、移位操作时是按32位来做运算,赋值时再按类型做取舍。
5、这个问题出在按Byte类型赋值时舍掉了一些数据位。
 
我个人的理解:
W: 00000000 00000000 10011100 01000000
B = W shr 11 = 00000000 00000000 00000000 00010011 = 19

G = W Shl 5 Shr 11 = 00000000 00000000 00000000 00100010 = 34

R = W Shl 11 Shr 11 = 00000000 00000000 00000000 00000000 = 0

B Shl 11 = 00000000 00000000 10011000 00000000 = 38912
G Shl 5 = 00000000 00000000 00000100 01000000 = 1088

B + G + R = 00000000 00000000 10011100 01000000 = 40000

不知道错在哪了
 
G = W Shl 5 Shr 11 = 00000000 00000000 00000000 00100010 = 34
这一步不对,原题是10位.就算是11位也不对,先向左5,后向右11.
 
晕.......这也讨论这么多? 很明显是在位移的过程中舍位的问题嘛~

错就错在那个shr 11和shr 10上面
4000转换2进制为111110100000 向右位移11位为1,而再shl 11以后为100000000000
也就是说,后面的11110100000(1952)被舍弃掉了
shr 10同理

如果还不明白,可以这样理解 对于正数,shr n就是整除2的n次方
2^11=2048 也就是说 4000 shr 11=4000 div 2048=1 而 1 shl 11=1*2048=2048 ----> 4000-2048=1952 也就是被舍掉的那部分
明白了吧,整除2^11以后的余数被丢掉了

如果不是用4000 而是用4096(2^12)来进行上面的测试就不会错了,因为4096可以被2^11整除,所以没有余数问题
 
后退
顶部