I need a math wiz to help solve this ^^

Pages: 1234
Hello everyone,

I need help with something. I want to be able to compile 8bit numbers into a full sized integer. Here is the code I have for that:
1
2
3
4
int CompileInt(int a, int b, int c, int d)
{
    return (a) + (b*256) + (c*65536) + (d*16777216);
}
Basically, this function is supposed to take in numbers that range from 0 to 256 and compile them into one big number.

Ok so the function works perfectly fine. The problem is, I don't know how to retrieve the numbers after I compile them. Anyone have ideas?

Thanks,
SuperSonic
How about bitmasks and bitshifting?

1
2
3
4
5
6
7
// get bits zero to 7
int bitsZeroToSeven = inputInt & (0x000000FF);

// get bits 8to 15
int bitsEightToFifteen = inputInt & (0x0000FF00);
// Now shift them along to occupy the lowest 8 bits
bitsEightToFifteen = bitsEightToFifteen >> 8;


and so on.
Ummm, I think I understand everything about this code except the last part that uses '>>'. What does that do?
<< and >> are bitshift operators.

If you shift a number left by 2 bits, then it has a similar effect as multiplying by 4:


(binary)
00110101  : 0x35
01101010  : 0x6A  (left shift 1)
11010100  : 0xD4  (left shift 2)
Ok, thank you guys =D
Hang on. How could I use this code in a function? This is what my function would look like:
int DecompileInt(int input, int id);
In this function, 'input' is the integer that will be decompiled, and 'id' is which integer to get (like the first one or the second etc). How can I implement Moschops's code for this?
Last edited on
There are 8 bits for each byte. So you can multiply the ID number by 8 and that is how many bits you need to shift. After shifting you can mask out the low 8 bits.
Ok, here is what I've got:
1
2
3
4
int DecompileInt(int input, int id)
{
    return (input & (id * 256)) >> (id * 8);
}

Of course, it doesn't work. If I use something like 200 as input and 0 as id, it will return 0 (instead of 200). Can you tell me what I did wrong?
here's what I've got:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int decompile(int input, int id)
{
     union
     {
           int a;
           unsigned char num[4];
           };
     a=in;
     return int(num[id-1]);
     }
int compile(int a, int b, int c, int d)
{
      union
      {
            int a;
            unsigned char num[4];
            };
      num[0]=a;
      num[1]=b;
      num[2]=c;
      num[3]=d;
      return a;
      }
Last edited on
Like all great code, that is both hideous and beautiful at the same time :)
Last edited on
@vilim: Thanks for the code, but if I use 0 for id, it will always return 119 =/
id goes from 1 to 4. Not 0.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

using namespace std;
int decompile(int input, int id)
{
     union
     {
           int a;
           unsigned char num[4];
           };
 a=input;
 return int(num[id-1]); // This takes care of counting from zero
}

int main()
{
  int z = 0x09080706;

  cout << decompile(z,4) << " "
       << decompile(z,3) << " "
       << decompile(z,2) << " "
       << decompile(z,1);
}

Last edited on
If you use 0..3 for id, then this is the code:
1
2
3
4
5
6
7
8
9
10
int decompile(int input, int id)
{
     union
     {
           int a;
           unsigned char num[4];
           };
     a=in;
     return int(num[id]);
     }

But in everyday uses we mosty use numbers from 1 on, not from 0, and that's why I made my pprogram for id-s from 1 to 4.
And btw, the title says you need a math wiz for this, and the most complex math in my program is id-1! XD
Thank you guys so much. It works now =D

And btw, the title says you need a math wiz for this, and the most complex math in my program is id-1! XD

Haha, yeah. I though it was going to be really complex xD
Technically, this is undefined behavior. You can't write to one member of a union and read from another. That said, I don't know of any compilers which don't handle this in reasonable way.
Even if it does work how you expect, it is still subject to system endianness.
Don't use unions for this -- it will break when you least expect it.

Use bit shifting.

Here is some code that takes some sequence of bytes and turns it into an integer value, and vice versa:
http://www.cplusplus.com/forum/beginner/31584/#msg171056

Here is a quick overview of endianness and composing/decomposing multi-byte values.
http://www.cplusplus.com/forum/general/11554/#msg54622

Hope this helps.
@cire: it isn't undifened behaviour at all! "union" means that all of the elements in it occupy the same memory! band since an int is 4 times bigger than a char array of 4, the behaviour is complety defined, as long as you initiate at least one member.
@viliml: yes it is!

$9.5 "In a union, at most one of the data members can be active at any time, that is, the value of at most one of the data members can be stored in a union at any time."


http://stackoverflow.com/questions/2310483/purpose-of-unions-in-c-and-c has some interesting observations.

Bjarne Stroustrup mentions it in passing in the c++11 faq:

http://www2.research.att.com/~bs/C++0xFAQ.html#unions

Obviously, it's illegal to write one member and then read another but people do that nevertheless (usually by mistake).
Pages: 1234