0

i'd like to store multiple values of blocks into an integer in the same way as i can convert an ip into an int. My problem is that i need to do this for n blocks, not only 4. Also i need to specifiy the maximum value of each block, which is allways the same for all blocks.

So, for the Example below, if i'd like to store the whole IP range my BlockCount is 4 and my BlockSize is 255, which is the max value of each block. But it seems not to work if i lower my BlockSize and/or BlockCount.

This is my first try, but it's not working correctly:

const int BlockSize = 100;
const int BlockCount = 3;

int shiftedValues = Shift(BlockSize, BlockCount);

for (int shiftedValue = 1; shiftedValue <= shiftedValues; shiftedValue++)
{
    for (int index = 0; index <= BlockCount; index++)
    {
        int blockValue = Unshift(index, shiftedValue);
    }        
}

private static int Shift(int blockSize, int blockCount)
{
    int result = 0;

    for (int i = 0; i < blockCount; i++)
    {
        result += ( blockSize << 8 * i );
    }

    return result;
}

private static int Unshift(int blockIndex, int shiftedValue)
{
    return ( shiftedValue >> ( blockIndex * 8 ) ) & 0xFF;   
}
endeffects
  • 431
  • 4
  • 15
  • 1
    There is only so much data (32 bits) you can fit into a single integer value, you know. – sstan Dec 16 '15 at 21:39
  • Is `BlockSize` the maximum value of each block? Also, care with things like `blockSize << 8 * i` as the order of operations here is probably "bitwise first" which may not be what you want. There are also only so many bits to play with before you need a BigInteger. – Draco18s no longer trusts SE Dec 16 '15 at 21:40
  • Yes, BlockSize defines the size of all blocks. Sorry, but I don't got the rest of your comment. I have no experience with bit shifting. – endeffects Dec 16 '15 at 21:46
  • That didn't answer the question. You said "size is size" I asked if "size is value." – Draco18s no longer trusts SE Dec 16 '15 at 21:47
  • Looks like you have some work to do. An int can only hold 32 bits. So BlockSize doesn't really seem to be the size of a block, yet the value to place in each of the "blocks"? Then there's the operator precedence issues. The there's the hard-coded 8-bit block size. Then there's the hard-coded block mask 0xFF etc. etc. etc. Maybe it would help if you could explain what you are trying to accomplish? Maybe you need an array instead? – James R. Dec 16 '15 at 21:48
  • Hm ok, the BlockSize is the maximum value of each block. – endeffects Dec 16 '15 at 21:49
  • @JamesR.i need to store and restore all possible variations of n values with the same value range in a single int. – endeffects Dec 16 '15 at 21:53
  • @endeffect so your block size could be at least 32 is it right? If no the answer is that what you are looking for is not possible. One integer = 32 bit = 32 is the maximum size for your block. Let me know if i understand right what you are asking for – Skary Dec 16 '15 at 22:09
  • @Skary no sorry, i don't understand it. If i'm able to store an ip like 255.255.255.255 as integer why should i not be able to store something like 150.150.150 in 3 blocks with a maximum value of 150? – endeffects Dec 16 '15 at 22:13
  • @endeffect yes you can because log 2 of 150 is about 7 and 7 * NUMBER_OF_BLOCKS = 21 and 21 < 32 the limit. You can not store 4 blocks where maximum value is 1024 for example. Let me understand if the constraint i show you is applicable to your scenario, if is not you may change your approach to the problem PS : when i say block size i talk about block size length in its binary representation – Skary Dec 16 '15 at 22:19
  • I'm fine with this limitiation because my blocksize length is not greater than 200. But the code snippet i tried to adapt seems not to work correctly in this case. – endeffects Dec 16 '15 at 22:25
  • @endeffects ok let me know if you find usefull my solution – Skary Dec 17 '15 at 09:43
  • @Skary thanks alot for your help, i'm testing your solution at the moment. i just wonder why it is more complex than i thought. – endeffects Dec 17 '15 at 09:55
  • C# does not provide ad easy access to bits (even if support some bitwiser operation) it's more complex but easy (and really faster) rely on bool arrays and serialize them throught BitArray object when needed. (bools are byte 0 or 1 so they are really fast and simple but expensive in memory, BitArray internally are converted from bool arrays to int arrays packed each other so they are cheaper but a little bit slower). Finally the extension methods are an overkill for that problem, but may be usefull to you if you need to reuse them – Skary Dec 17 '15 at 10:22

1 Answers1

1

The code above is my solution, it's pretty simple code, but feel free to ask clarification about it.

class Program
{
    static void Main(string[] args)
    {
        int [] items = { 150 , 78 , 44 } ;
        int x = Program.Pack ( items , 150 ) ;
        int [] unpacked = Program.UnPack ( x , 150 , 3 ) ;
    }

    public static int Pack ( int[] blocks , int blockSize )
    {
        int size = (int)Math.Ceiling(Math.Log(blockSize, 2));
        int len = size * blocks.Length;

        if (len > 32)
            throw new Exception("Int Limit Exceeded");

        if ( blocks.Any ( x => x > blockSize ) )
            throw new Exception ( "There are some blocks that exceede the maximum block size" );

        List<bool> bools = new List<bool>();
        bools = bools.InitBoolArray(32);

        int i = 0 ;
        foreach (int block in blocks)
        {
            BitArray temp = block.ToBinary().Take(size);

            for ( int j = 0 ; j < size ; i++ , j++ )
                bools[i] = temp.Get(j);
        }

        return (new BitArray ( bools.ToArray() ) ).ToNumeral() ;
    }

    public static int[] UnPack ( int entry , int blockSize , int blockCount )
    {
        BitArray number = entry.ToBinary();
        int size = (int)Math.Ceiling(Math.Log(blockSize, 2));

        if (size > 32)
            throw new Exception("Int Limit Exceeded");

        List<int> result = new List<int>();

        for (int i = 0; i < blockCount; i++)
        {
            BitArray temp = number.Take(size);
            number = number.Shift (size );
            result.Add(temp.FitSize(32).ToNumeral());
        }

        return result.ToArray() ;
    }
}

There extension method used

public static class BinaryConverter
    {
        public static BitArray ToBinary(this int numeral)
        {
            return new BitArray(new[] { numeral });
        }

        public static int ToNumeral(this BitArray binary)
        {
            if (binary == null)
                throw new ArgumentNullException("binary");
            if (binary.Length > 32)
                throw new ArgumentException("must be at most 32 bits long");

            var result = new int[1];
            binary.CopyTo(result, 0);
            return result[0];
        }

        public static BitArray Take (this BitArray current, int length )
        {
            if (current.Length < length)
                throw new Exception("Invalid length parameter");

            List<bool> taken = new List<bool>();

            for (int i = 0; i < length; i++)
                    taken.Add(current.Get(i));

            return new BitArray(taken.ToArray());
        }

        public static BitArray Shift (this BitArray current, int length )
        {
            if (current.Length < length)
                throw new Exception("Invalid length parameter");

            List<bool> shifted = new List<bool>();

            for (int i = 0; i < current.Length - length; i++)
                shifted.Add(current.Get(length + i));

            return new BitArray(shifted.ToArray());
        }

        public static BitArray FitSize (this BitArray current, int size)
        {
            List<bool> bools = new List<bool>() ;
            bools = bools.InitBoolArray(size);

            for (int i = 0; i < current.Count; i++)
                    bools[i] = current.Get(i) ;

            return new BitArray(bools.ToArray());
        }

        public static List<bool> InitBoolArray(this List<bool> current, int size)
        {
            List<bool> bools = new List<bool> ();

            for (int i = 0; i < size; i++)
                bools.Add(false);

            return bools ;
        }
    }
Skary
  • 1,322
  • 1
  • 13
  • 40
  • Once again thanks alot for your help and the time you spent here. I was able to adapt your solution into my original problem and now it seems to work fine: http://stackoverflow.com/questions/34287581/self-training-algorithm – endeffects Dec 17 '15 at 10:49
  • i think there is a bug, if i pack items and looping from int i = 1 to i <= Program.Pack(items, 150) to unpack all smaller packages, i'm getting values above the block length. – endeffects Dec 18 '15 at 14:19
  • i do not understand you code. Program.Pack( [LIST_OF_SMALL_INT , SMALL_INT_MAX_SIZE) return and integer that is packed version of small int. Why you are looping using that int (has no numerical meaning) as index ? – Skary Dec 18 '15 at 16:22