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

9

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 the byte m (reverse operation) again?

    
asked by anonymous 17.07.2017 / 19:20

5 answers

14

It seems that you lack the conceptual basis on how values are encoded in binary.

If each binary digit can only be zero or one, a binary digit only allows you to code 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 a given length n is capable of encoding is x = 2 n . So in 8 bits (1 byte) you can code 256 different values. In the case of integers, it can be -128 to 127 from 0 to 255, or some other more exotic division. But anyway, there are no more than 256 values in 1 byte.

So, if you have a value that needs more than 1 byte to be stored, you can not fit it into 1 byte without losing information. In your% wrapper example, for example, the conversion gives 255 because it is the largest integer that fits into 1 byte. Any value greater than 255 gives this same result when converted to byte, so you can not undo the operation, since countless values (infinites, actually) give this same result.

    
17.07.2017 / 19:48
11

No space

You want to get something from 1 kg and save in a 500g container, it will throw away 500g, then you want to have the 1Kg back. There is only one possibility, save the 500g elsewhere. But why do that? Does not make any sense. If you need to keep the complete information, use it fully.

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

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

So there is not enough bit quantity 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.

Actually even using a short might be avoided. In some cases where memory gain will actually occur, and few cases occur and it is necessary , overall it is worse try to use a smaller type than the one most appropriate for the processor, so leave a int ( Int32 ), unless you are sure you have won.

Workaround

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

For example, you are using 2017, I believe this is a full year with a century, but it may not need the century, so subtract 2000 and save only the year that fits a byte . If you have years prior to 2000, you can subtract 1900, of course that which is above 100 you know is 21st century, what is below is 20th century.

Simplistically it would look 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 running on .NET Fiddle . And no Coding Ground . Also I put GitHub for future reference .

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

    
17.07.2017 / 19:41
9

Because a byte is usually composed of * 8 bits, the largest value you can represent is usually 255.

Explanation: integers are generally represented as power sums of 2. Each bit with a value of zero equals zero, and each bit with value 1 represents the value 2 n , where n is the position (usually from right to left) of the zero-indexed bit.

Here are some examples:

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

etc., etc., up to the largest value that is 255 when the bit layout is as follows:

1111 1111 = 255

3 + 2 2 + 2 1 + 2 0 .

So, to represent any values greater 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 to extract an integer value greater than 255 from only eight bits.

It might have been possible with floating point numbers , but generally the smallest floating point type, the < in> float , usually occupy at least four bytes in memory. In addition, you would still run the risk of not getting the desired result because of precision problems if you want to implement one-byte floating point.

Therefore:

  • If you want to use byte for compaction reasons, it's best to review your strategies;
  • If you need to use the byte type for any other reasons (ie homework), you will need more bytes.

* I'm not making bad joke here, different size bytes exist although they are almost as rare as well as Palmeiras world cups.

    
17.07.2017 / 19:53
3

A value of 16 bits is best represented as a short int instead of to use BitConvert.GetBytes (short).

Therefore, as an alternative:

byte lowByte = (byte) (numero & 0xff);
byte highByte = (byte) ((numero >> 8) & 0xff);
    
17.07.2017 / 19:41
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);
    
17.07.2017 / 19:49