Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Rotate left 2 bits (like assembler)
#11
My entry function:

[syntax="QBasic"]
function rol%(orig as integer)
rol% = (((orig * 4) or (orig \ (2^14))) * sgn(orig)) and &HFFFF
end function
[/syntax]

Program used for testing it:

[syntax="QBasic"]
declare function rol%(orig as integer)

cls

numIn$ = "x"
do
line input "Number (blank to quit): ", numIn$
print rol%(val(numIn$))
loop until numIn$ = ""

end


function rol%(orig as integer)
rol% = (((orig * 4) or (orig \ (2^14))) * sgn(orig)) and &HFFFF
end function
[/syntax]

Tested in FreeBASIC, not QB.
img]http://www.cdsoft.co.uk/misc/shiftlynx.png[/img]
Reply
#12
Quote:My entry function:

[syntax="QBasic"]
function rol%(orig as integer)
rol% = (((orig * 4) or (orig \ (2^14))) * sgn(orig)) and &HFFFF
end function
[/syntax]

Program used for testing it:

[syntax="QBasic"]
declare function rol%(orig as integer)

cls

numIn$ = "x"
do
line input "Number (blank to quit): ", numIn$
print rol%(val(numIn$))
loop until numIn$ = ""

end


function rol%(orig as integer)
rol% = (((orig * 4) or (orig \ (2^14))) * sgn(orig)) and &HFFFF
end function
[/syntax]

Tested in FreeBASIC, not QB.

(orig * 4) will overflow in QB
Reply
#13
Brilliant, ShiftLynx!

I had my doubts, but I ran it in QB from 0 to 32767, and it works fine, giving the same results as Mango's and mine.

Yes, Mango, you would think that the (orig * 4) would overflow, but it doesn't. Maybe it waits for the final result of the whole expression --- who knows?

Mango's solution works fine. However, in all fairness the solution by ShiftLynx is indeed more elegant, and also works fine. So, ShiftLynx is the winner so far.

One question: Why does the expression need the AND &HFFFF when it's only working with integers anyway?
*****
Reply
#14
Quote:One question: Why does the expression need the AND &HFFFF when it's only working with integers anyway?
*****

I just used it so that it would work in FreeBASIC too... If I remember correctly, integers in FB are 32-bit.

Thanks for the comments on it.
img]http://www.cdsoft.co.uk/misc/shiftlynx.png[/img]
Reply
#15
OOOPS, I screwed up, guys. :oops:

The original challenge was:
"take a given 16 bit value and do a rotate left 2 bits."

SHIFTLYNX: your solution works fine for any value from 0 to 32767, which covers 15 bits. Further testing of your solution shows that for any value with bit 16 on, it does not work. For example: a value of -1, which is hex FFFF, should give a result of FFFF also, and -2, which is FFFE should give FFFB. Your solution gives 4 and 8 respectively.
I tried it under FB, and the results are the same.

So, MANGO has the only solution that works for all 16 bit values. Therefore, MANGO is still the winner so far.
*****
Reply
#16
Fixed:

[syntax="QBasic"]
function rol%(orig as integer)
orig = orig and &HFFFF
rol% = (((orig * 4) or (orig \ (2^14))) * sgn(orig)) and &HFFFF
end function
[/syntax]

Testing code:
[syntax="QBasic"]
declare function rol%(orig as integer)

cls

numIn$ = "x"
do
line input "Number (blank to quit): ", numIn$
print rol%(val(numIn$))
loop until numIn$ = ""

end


function rol%(orig as integer)
orig = orig and &HFFFF
rol% = (((orig * 4) or (orig \ (2^14))) * sgn(orig)) and &HFFFF
end function
[/syntax]
img]http://www.cdsoft.co.uk/misc/shiftlynx.png[/img]
Reply
#17
ShiftLynx,

The original challenge said: "using only QB instructions".
I told you that values of -1 and -2 didn't work, well they still don't work with QB in your new version.

Yes, it looks like they work in FB, but that opens up another realm of testing beyond the specifications of the original challenge. Sorry.
*****
Reply
#18
This one rotates 0-16 bits of any 16 bit number to the left or right. It's a bit more challenge then just 2 bits and it's still only one line per rotate function (i hope by now you don't coun't comments as lines).

Code:
defint a-z

declare sub         printBin        ( num as long )
declare function    rotLeft&        ( num as long, bits as integer )
declare function    rotRght&        ( num as long, bits as integer )

dim i as integer


    cls    
    for i = 0 to 16
        printBin rotLeft&( &h0de0, i )
    next i    
    
    sleep
    cls    
    
    for i = 0 to 16
        printBin rotRght&( &h0de0, i )
    next i        




'' :::::::::
'' name: rotLeft
'' desc: Rotates a number to the left
''       OBS! Cannot rotate more then 16 bits or handle numbers larger
''            then 16 bits
''
'' parm: num        - the number to rotate
''       bits       - bits to rotate number
''
'' retn: Rotated number
''
'' :::::::::
function rotLeft& ( num as long, bits as integer )
    rotLeft& = ((num * clng(2^bits)) and (2^16-1)) or (num and (2^bits-1)*2^(16-bits))\2^(16-bits)    
end function



'' :::::::::
'' name: rotRght
'' desc: Rotates a number to the right
''       OBS! Cannot rotate more then 16 bits or handle numbers larger
''            then 16 bits
''
'' parm: num        - the number to rotate
''       bits       - bits to rotate number
''
'' retn: Rotated number
''
'' :::::::::
function rotRght& ( num as long, bits as integer )
    rotRght& = ((num and (2^16-1)) \ 2^bits) or ((num and (2^bits-1))*2^(16-bits))
end function



'' :::::::::
'' name: printBin
'' desc: Prints out a 16 bit binary number to the console
''
'' parm: num        - the number print
''
'' retn: nothing
''
'' :::::::::
sub printBin ( num as long )
    dim i as integer    
    
    for  i = 15 to 0 step -1
        print ltrim$( str$( (num and 2^i)\2^i ) );
    next i
    
    print
end sub



This one on the other hand just rotates 2 bits of a 16 bit number to the left, just thought i'd add this seing how you jugded the last challenge.

Code:
function rotLeft& ( num as long )
    rotLeft& = ((num * 4) and &hffff) or (num and &hc000)\&h4000
end function
oship me and i will give you lots of guurrls and beeea
Reply
#19
Blitz,

Sorry for the delay. I had no Internet service yesterday.

Regarding the following solution:
Code:
function rotLeft& ( num as long )
    rotLeft& = ((num * 4) and &hffff) or (num and &hc000)\&h4000
end function

I put it into a test program, and found the following problems:

1) For a num from 0 to 32766, it produces a 17 bit result.
Examples: 16384 gives a result of hex 10001 instead of 1,
......... and 32766 gives a result of hex 1FFF9 instead of FFF9.

2) For a num of -1, the result is FFFFFFFF, way beyond 16 bits.

3) For a num of -2, the result is also FFFFFFFF --- weird.

Note: Since you are working with long intergers, your hex numbers should end with an & to make them long also. Example: instead of &hc000, it should be &hc000&.

Take a careful look at Mango's step-by-step solution, and figure out what yours is missing or why it's different.

Regarding your comments: Pleaase take this as constructive criticism. Notice that in your original global solution, you commented everything except the actual logic of the solution, which has a multiply, 2 ands, an or, an integer divide, and uses 3 hex constants, with no explanation whatsoever.
*****
Reply
#20
Well well, qb has once again proven to me how much it really sucks. And real compiler should convert everything in an expression to the largest datatype, especially constants. Thus & wouldn't be needed in an expression where you are using longs. But looks like qb doesn't do that. So here you go, this one works

Code:
function rotLeft& ( num as long )
    rotLeft& = ((num * 4) and &hffff&) or (num and &hc000&)\&h4000&
end function

Longs are needed becuase otherwise the IDE will report an overflow in many cases. When compiled they aren't needed. I tested all the cases you talked about, all work fine as you'll see here

16384
0100000000000000
0000000000000001
0000000000000100
0000000000010000
0000000001000000
0000000100000000
0000010000000000
0001000000000000

-1
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111
1111111111111111

-2
1111111111111110
1111111111111011
1111111111101111
1111111110111111
1111111011111111
1111101111111111
1110111111111111
1011111111111111
1111111111111110

Tested with
Code:
cls    
    test& = somenumber.....
    for i = 0 to 8        
        printBin test
        test = rotLeft&( test )
    next i


How does it work? Simple, get the top 2 bits and move them down 14 bits, shift the number 2 bits to the left and combine it with the result of the previous operation. That's what bit rotating is. No branches needed, it's all simple logic.

Code:
shl 2      |1100010100000010|

           -------------------
         11|0001010000001000|
           -------------------
      

           |1100010100000010|
and        |1100000000000000|
           -------------------
shr 14     |1100000000000000|
           -------------------
           |0000000000000011|00000000000000
           -------------------


or         |0001010000001000|
           |0000000000000011|
           -------------------
           |0001010000001011|
          
There, done
oship me and i will give you lots of guurrls and beeea
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)