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

If I create the following expression:

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

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

 10
Author: CypherPotato, 2017-07-17

5 answers

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

If each binary digit can only be zero or one, a binary digit can only encode two values. In the same way, two digits allow you to encode up to 4 values:

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

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

So if you have a value that needs more than 1 byte to be stored, there's no way to make it fit into 1 byte without losing information. In your 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 by being converted to byte, and so there is no way to undo the operation, since numerous values (infinite, in fact) give this same result.

 16
Author: bfavaretto, 2017-07-17 17:48:25

Has no space

You want to take something 1kg and store in a container of 500g, will throw away 500g, then you want to have the 1Kg back. There is only one possibility, to store the 500g elsewhere. But why do that? It doesn't make sense. If you need to keep the information complete, use it complete.

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

Um short it has 2 bytes (16 bits), and can represent 65536 different numbers. But it has a different thing than byte, it is signaled, i.e. there is a bit indicating if it is negative, then the largest possible positive number is 32783.

Then does not have enough bits in a byte to represent 2017 that would need a minimum of 11 bits, but since you can not Reserve memory with a broken byte, 16 bits is adopted.

In fact even the use of a short should perhaps be avoided. In some cases where the memory gain will indeed occur, and few cases occurs and it 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 won.

Workaround

Now, if you really need to reduce the size, which I doubt is as necessary as that, is it possible adopt some criteria depending on what you are using. 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 the century, so subtract 2000 and save only the year that fits one one byte. If you have years from before 2000, you can subtract 1900, of course what is above 100 you know is 21st century, what is below is 20th century.

In simplified form 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();
}

See working on ideone. And no .NET Fiddle. Also I put on GitHub for future reference .

I still think a lot of gambiarra to probably little gain. You would have to keep controlling this in every application. Or you could create a one-byte type that abstracts all of this, which will still likely be a lot of effort for little gain, as there is no context can not assert.

 12
Author: Maniero, 2020-06-11 14:45:34

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

Explanation: integers are generally represented as sums of powers of 2. Each bit with zero value represents zero even, and each bit with value 1 represents the value 2 n , where n is the position (usually 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., even the largest value that is 255 when the bit arrangement is as follows:

1111 1111 = 255

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

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

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

Might be possible with floating point numbers, but in general the smallest floating point type, float, usually takes up at least four bytes in memory. In addition, you would still run the risk of not getting the desired result due to accuracy issues if you want to implement one byte floating point in marra.

Therefore:

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

*I'm not making bad jokes here, bytes of different sizes exist despite being almost as rare as Palmeiras world wide.

 9
Author: Garoto de Programa, 2017-07-17 17:53:53

A 16-Bit value is better represented as a short rather than int to use BitConvert.GetBytes (short).

So alternatively:

byte lowByte = (byte) (numero & 0xff);
byte highByte = (byte) ((numero >> 8) & 0xff);
 3
Author: Tábata Gonçalves, 2017-07-17 17:41:10

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 the other way around.

    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);
 2
Author: mcamara, 2017-07-17 17:49:50