user730917
user730917

Reputation: 13

Number of bytes to encode a number

This might be a beginner Java question but I would like to be able to calculate the number bytes it will require to store a whole number. And to convert that number into a byte array. Its do with some TLV encoding that I am performing. I realise that Java stores everything in twos completement but I am ignoring that, I am just interested in keeping the binary representation.

For example, if you had the number 256 it would take 2 bytes (as 1 byte can store 2^8-1, i think) then I would like to convert that number into a byte array.

Where:

byte[0] = 1111 1111

byte[1] = 0000 0001

Thanks for any help.

Upvotes: 1

Views: 3470

Answers (3)

Anatolij
Anatolij

Reputation: 607

You can use Math.ceil(Math.log(number) / Math.log(2)) to get number of bits to store your number in binary format. Devide by 8 and you will get bytes to store your number.

Upvotes: 4

Marcello DeSales
Marcello DeSales

Reputation: 22329

Since Java only contains log10, you have to first convert it to log2. Consider the definition of change of base enter image description here

We can then write Math.ceil(Math.log(256) / Math.log(2)) for the suggested answers... For instance, you would need 9 bits to save 256 or 2 bytes:

    System.out.println(Integer.toBinaryString(256));
    int numberBits = (int) Math.ceil(Math.log(256) / Math.log(2)) + 1;
    int numberBytes = (int) (Math.ceil(Math.log(256) / Math.log(2)) / 8) + 1;
    System.out.println(numberBits);
    System.out.println(numberBytes);

100000000
9
2

I was just intrigued in how to get the byte[] of your requirement (to have them in revert order)... I started the implementation of the following test class with a char[]. Then, it came to my mind you could also a BitSet if you need operations over the bit set.

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;

public class TestRevertBitSet {

    public static class RevertableBitSet {

        private BitSet bitSet;
        private boolean flipped;

        private RevertableBitSet(BitSet bitSet) {
            this.bitSet = bitSet;
        }

        public static RevertableBitSet makeNew(char[] bitArray) {
            BitSet byteValue = new BitSet(bitArray.length);
            for (int i = 0; i < bitArray.length; i++) {
                if (bitArray[i] == '1') {
                    byteValue.flip(i);
                }
            }
            RevertableBitSet r = new RevertableBitSet(byteValue);
            if (r.hasZeroCardinality()) {
                r.flipAllBitsTrue();

            } else {
                r.revertBitsOrder();
            }
            return r;
        }

        public boolean hasAllBitsFlip() {
            return this.flipped;
        }

        /**
         * @return if all the bits are set.
         */
        public boolean hasZeroCardinality() {
            return this.bitSet.cardinality() == 0;
        }

        /**
         * Flips all bits from the given bitSet to true.
         */
        public void flipAllBitsTrue() {
            this.bitSet.set(0, this.bitSet.size());
            this.flipped = true;
        }

        /**
         * Reverts the bits sequence. For instance, from 01100 to 00110.
         */
        public void revertBitsOrder() {
            for (int i = 0; i < 4; i++) {
                boolean nthBit = this.bitSet.get(i);
                this.bitSet.set(i, this.bitSet.get(7 - i));
                this.bitSet.set(7 - i, nthBit);
            }
        }

        /**
         * @return a char array with values based on the bit indexes of the
         *         given bit set.
         */
        public char[] toCharArray() {
            char[] bitChars = new char[8];
            for (int i = 0; i < bitChars.length; i++) {
                bitChars[i] = bitSet.get(i) ? '1' : '0';
            }
            return bitChars;
        }

        /**
         * @param bitIndex
         * @return the boolean value of the given bit index.
         */
        public boolean getBitBooleanAtIndex(int bitIndex) {
            if (bitIndex > 7) {
                return false;
            }
            return this.bitSet.get(bitIndex);
        }

        /**
         * @param byteSetsList
         *            is the list of BitSet.
         * @return the integer representation of the entire bit set.
         */
        public static int convertSetToInteger(
                List<RevertableBitSet> byteSetsList) {
            int sum = 0;
            int index = 0;
            for (RevertableBitSet bitSet : byteSetsList) {
                if (bitSet.hasAllBitsFlip()) {
                    for (int i = 0; i < 8; i++) {
                        index++;
                    }
                    continue;
                }
                for (int i = 7; i >= 0; i--) {
                    int bit = bitSet.getBitBooleanAtIndex(i) ? 1 : 0;
                    int intValue = (int) Math.pow((double) 2, (double) index++)
                            * bit;
                    sum = sum + intValue;
                }
            }
            return sum;
        }

        @Override
        public String toString() {
            StringBuilder b = new StringBuilder();
            b.append("[ ");
            for (int i = 0; i < 7; i++) {
                b.append(i);
                b.append(" , ");
            }
            b.delete(0, b.length() - 2);
            b.append(" ]");
            return b.toString();
        }
    }

    public static void main(String[] args) throws IOException {

        int decimalNumber = 256;
        System.out.println("Decimal Number: " + decimalNumber);
        System.out.println(Integer.toBinaryString(decimalNumber));
        int numberBits = (int) Math.ceil(Math.log(decimalNumber) / Math.log(2)) + 1;
        int numberBytes = (int) (Math.ceil(Math.log(decimalNumber)
                / Math.log(2)) / 8) + 1;
        System.out.println("Number of bits: " + numberBits);
        System.out.println("Number of bytes: " + numberBytes);

        List<RevertableBitSet> bytesSet = new ArrayList<RevertableBitSet>();

        int bitsCounter = -1;
        char[] binaryChars = Integer.toBinaryString(decimalNumber)
                .toCharArray();
        char[] currentChars = new char[8];
        Arrays.fill(currentChars, '0');
        for (int i = binaryChars.length - 1; i >= 0; i--) {
            if (bitsCounter + 1 <= 7) {
                currentChars[++bitsCounter] = binaryChars[i];

            } else {
                RevertableBitSet bitSet = RevertableBitSet
                        .makeNew(currentChars);
                bytesSet.add(bitSet);

                bitsCounter = -1;
                Arrays.fill(currentChars, '0');
                currentChars[++bitsCounter] = binaryChars[i];
            }
        }

        bytesSet.add(RevertableBitSet.makeNew(currentChars));

        System.out.println("------------");

        for (RevertableBitSet bitSet : bytesSet) {
            System.out.println(Arrays.toString(bitSet.toCharArray()));
        }

        System.out.println("------------");
        System.out.println("Number: "
                + RevertableBitSet.convertSetToInteger(bytesSet));
    }
}

The output of the execution of the main method is:

Decimal Number: 256
100000000
Number of bits: 9
Number of bytes: 2
------------
[1, 1, 1, 1, 1, 1, 1, 1]
[0, 0, 0, 0, 0, 0, 0, 1]
------------
Number: 256

Larger numbers as well work...

Decimal Number: 33456176
1111111101000000000110000
Number of bits: 26
Number of bytes: 4
------------
[0, 0, 1, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 1, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 1]
------------
Number: 33456176

Upvotes: 3

LueTm
LueTm

Reputation: 2380

The binary logarithm (log2) of a number gives you the number of bits needed to display the number. From there it should be easy to get to bytes.

Upvotes: 3

Related Questions