Is it possible to convert a 16-bit number to a single byte?

Asked

Viewed 1,059 times

11

If I create the following expression:

Int16 numero = 2017;
byte m = (byte) numero;

m will have the value of 225. Okay, how do I get 2017 from the byte m (reverse operation) again?

  • 1

    16 bits are 2 bytes. Can’t convert without throwing information away.

5 answers

16


You seem to be missing the conceptual basis for how values are encoded in binary.

If each binary digit can only be zero or one, a binary digit can only encode two values. Similarly, two digits allow encoding up to 4 values:

00 - 0
01 - 1
10 - 2
11 - 3

The general rule is that the amount of values a binary number of given length n is able to encode is x = 2n. Therefore, in 8 bits (1 byte) you can encode 256 distinct values. In the case of integers, it can be from -128 to 127 from 0 to 255, or some other more exotic division. But anyway, they don’t fit more than 256 values in 1 byte.

Thus, if you have a value that needs more than 1 byte to be stored, there is no way to make it fit in 1 byte without losing information. In his example of 2017, for example, the conversion gives 255 because it is the largest integer that fits in 1 byte. Any value greater than 255 gives this same result when converted to byte, and thus has no way to undo the operation, since numerous values (infinite, in fact) give this same result.

12

No room

You’re going to take something 1 kg and put it in a 500 g container, you’re going to throw away 500 g, and then you want to take the 1 kg back. There is only one possibility, to save the 500g elsewhere. But why do this? It is meaningless. If you need to keep the information complete, use it fully.

In a kind byte fit 8 bits, as the bit only has 2 states, 2 to the 8 we have a combination of 256 different numbers, so in a byte we cannot represent a number greater than 255, since it starts from 0.

A short has 2 bytes (16 bits), can represent 65536 different numbers. But it has something other than byte, it is flagged, ie there is a bit indicating if it is negative, then the largest possible positive number is 32783.

So there’s not enough bits in one byte to represent 2017 that would need a minimum of 11 bits, but as we can not reserve memory with a broken byte, 16 bits is adopted.

Actually even the use of a short perhaps it should be avoided. In some cases where memory gain will actually occur, and few cases occurs and is necessary, in general it is worse to try to use a smaller type than the most suitable for the processor, so leave a int (Int32), unless you’re sure you’ve won.

Workaround

Now, if you really need to reduce the size, which I doubt is so necessary, it is possible to adopt some criteria depending on what you use. You can throw away information that you know can be retrieved later by convention. This works in some cases.

For example, you’re using 2017, I believe this is a full year with century, but maybe you don’t need century, so subtract 2000 and save only the year that fits one byte. If you have years before 2000, you can subtract 1900, of course whatever’s above 100 you know it’s 21st century, what’s below is 20th century.

In a simplified way it would be something like this:

using System;
using System.Diagnostics.Contracts;

public class Program {
    public static void Main() {
        short numero = 2017;
        var m = new ShortYear(numero);
        Console.WriteLine(m);
    }
}
//provavelmente teria implemnetações de operadores, outros métodos e das interfaces
//IFormattable, IConvertible, IComparable<ShortYear>, IEquatable<ShortYear> e outras
public struct ShortYear {
    public byte Year;
    public const short Century = 1900;
    public ShortYear(short value) {
        Contract.Ensures(value >= 1900 && value < 2156);
        Year = (byte)(value - Century);
    }
    public ShortYear(int value) {
        Contract.Ensures(value >= 1900 && value < 2156);
        Year = (byte)(value - Century);
    }
    public static implicit operator short(ShortYear value) => (short)(value.Year + Century);
    public static implicit operator int(ShortYear value) => value.Year + Century;
    public override int GetHashCode() => Year.GetHashCode();
    public override String ToString() => (Year + Century).ToString();
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

I still think a lot of skulking for probably little gain. You’d have to keep track of that in every application. Or you could create a kind of a byte that abstracts all of this, which is still likely to be a lot of effort for little gain, as there is no context to affirm.

9

Since a byte is usually composed* of eight bits, the highest value you can represent in general is 255 even.

Explanation: Integers are represented in general as sums of powers of 2. Each bit with zero represents zero even, and each bit with 1 represents 2n, where n is the position (usually from right to left) of the zero-indexed bit.

Here are some values for example:

0000 0001 = 1
0000 0010 = 2
0000 0100 = 4
0000 0101 = 5
0001 0000 = 32
0010 0001 = 33

Etc., etc., up to the highest value that is 255 when the bit array is as follows:

1111 1111 = 255

For 255 = 27 + 26 + 25 + 24 + 23 + 22 + 21 + 20.

So to represent any values greater than that, we need more bits. For this reason the numerical types of most languages have sizes ranging from sixteen to sixty-four bits.

Unfortunately, exactly for this reason, it is not possible to extract an integer value greater than 255 from just eight bits.

Maybe it was possible with floating point numbers, but in general the smallest type of floating point, the float, usually takes at least four bytes in memory. In addition, you would still run the risk of not getting the desired result due to precision problems if you want to implement a floating point of one byte in the box.

Therefore:

  • If you want to use the type byte for reasons of compaction, it is better to review your strategies;
  • If you need to use the type byte for any other reasons (i.e.: homework), you will need more bytes.

*I’m not making sick jokes here, bytes of different sizes exist although they are almost as rare as Palmeiras.

3

A 16-bit value is best represented as a short instead of int for using Bitconvert.Getbytes(short).

So as an alternative:

byte lowByte = (byte) (numero & 0xff);
byte highByte = (byte) ((numero >> 8) & 0xff);

2

Impossible to put 16 bits in 1 byte. What you can do is put in an array of bytes with Bitconverter and then do the process backwards.

    Int16 numero = 2017;
    var StrToByte = BitConverter.GetBytes(numero);
    byte[] temp = new byte[4];
    StrToByte.CopyTo(temp, 0);
    StrToByte = temp;
    var i = BitConverter.ToInt32(StrToByte, 0);
    Console.WriteLine(i);

Browser other questions tagged

You are not signed in. Login or sign up in order to post.