A little brain teaser

Started by
7 comments, last by Ectara 9 years, 5 months ago

I'm not saying this is overly difficult or anything to that effect, but I found myself faced with the following problem: extract the low and high dwords from a 64-bit variable and display them. A simple problem, but it took me a while to find out (the hard way) that the Visual Studio native visualizer doesn't support any bitwise operations other than right shift.

After a few minutes of tinkering I came up with a straightforward solution, but now I'm wondering how many ways there are to do this.

So, to recap, given the 64-bit sample value "515396075660", extract the low and and high dwords using a combination of only RSH (>>) and any non-bitwise operators except for modulo.

Points go to how few different operator types you need. I needed three, but I cheated at least one.

[spoiler]

w = val - ((val >> 32) * 4294967296), where 4294967296 = (1 << 32)

h = val >> 32

[/spoiler]

Advertisement

4294967296 = 1 << 32, not (1 << 32) + 1. You've basically emulated a variant of the operation "modulo 2^32", which is the same as masking all but the lowest 32 bits. I doubt it can be done with less than three different non-bitwise operators except for SHR, though. But, thinking outside the box, cast the 64-bit integer to a structure of two 32-bit integers? That may be cheating though. Another option: convert your 64-bit integer to a 16-character hexadecimal string, and cut it in half? You never said the output needed to be in integer format smile.png

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

I can do it with two: left-shift and bitwise-and.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Can you do a left shift by using a negative value as right shift amount?

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

I can do it with two: left-shift and bitwise-and.

You must have ment the right shift.


low=val&(the constant of 32th power of two)

high=val>>32


So, to recap, given the 64-bit sample value "515396075660", extract the low and and high dwords using a combination of only RSH (>>) and any non-bitwise operators.

Non-bitwise permitting +, -, *, /, and % ?

high = val / 4294967296; // or high = val >> 32; if having one right-shift is a requirement

low = val % 4294967296;

// low = 140, high = 120

I feel like I'm missing something.


So, to recap, given the 64-bit sample value "515396075660", extract the low and and high dwords using a combination of only RSH (>>) and any non-bitwise operators.

Non-bitwise permitting +, -, *, /, and % ?

high = val / 4294967296; // or high = val >> 32; if having one right-shift is a requirement

low = val % 4294967296;

// low = 140, high = 120

I feel like I'm missing something.

My bad - I neglected to mention natvis didn't accept modulo.

4294967296 = 1 << 32, not (1 << 32) + 1. You've basically emulated a variant of the operation "modulo 2^32", which is the same as masking all but the lowest 32 bits. I doubt it can be done with less than three different non-bitwise operators except for SHR, though. But, thinking outside the box, cast the 64-bit integer to a structure of two 32-bit integers? That may be cheating though. Another option: convert your 64-bit integer to a 16-character hexadecimal string, and cut it in half? You never said the output needed to be in integer format smile.png

Well - for the sake of the argument it doesn't matter, although for natvis it needs to be a resolvable expression that produces a valid numeric or regular string output :). @the typo - indeed, I blindly copied from the Windows Calculator, which treats all values as signed, meaning the number was off by one.

Can you do a left shift by using a negative value as right shift amount?

Hm - that's an interesting idea. I'll try it out when I get the chance.

I guess you wouldn't consider a union of an uint64_t and two uint32_ts either as anonymous struct or array (and no explicit shifts or bitwise operations at all) a valid solution?

I guess you wouldn't consider a union of an uint64_t and two uint32_ts either as anonymous struct or array (and no explicit shifts or bitwise operations at all) a valid solution?

To be honest I started this thread for fun because I had to go through 3 or 4 different solutions before I found one that didn't generate an error. Under those restrictions it just felt like a fun exercise, so I only wrote down the ones I had to work around. Like I stated in my original post, I only started this thread to see if there were other solutions that I didn't think about :).

high = val / 4294967296; // or high = val >> 32; if having one right-shift is a requirement
low = val - (high * 4294967296);

One more operation, I suppose. Alternatively, if the IDE doesn't try to be clever:

high = val / 4294967296;
low = (val * 4294967296) / 4294967296;

This topic is closed to new replies.

Advertisement