O C#, como muitas linguagens de tipagem estática, oferece vários tipos que representam números inteiros, cada um com seu próprio intervalo de valores. Na ponta inferior, o tipo sbyte tem valor mínimo de -128 e valor máximo de 127. Como em todos os tipos inteiros, esses valores estão disponíveis como <type>.MinValue e <type>.MaxValue. Na ponta superior, o tipo long tem valor mínimo de -9.223.372.036.854.775.808 e valor máximo de 9.223.372.036.854.775.807. Entre eles ficam os tipos short e int.
Os intervalos são determinados pela largura de armazenamento do tipo, conforme alocada pelo sistema. Por exemplo, um byte usa 8 bits e um long usa 64 bits.
Cada um dos tipos acima tem um equivalente sem sinal: sbyte/byte, short/ushort, int/uint e long/ulong. Em todos os casos, o intervalo de valores vai de 0 até o máximo negativo do tipo com sinal multiplicado por 2, mais 1.
| Tipo | Largura | Mínimo | Máximo |
|---|---|---|---|
| sbyte | 8 bit | -128 | +127 |
| short | 16 bit | -32_768 | +32_767 |
| int | 32 bit | -2_147_483_648 | +2_147_483_647 |
| long | 64 bit | -9_223_372_036_854_775_808 | +9_223_372_036_854_775_807 |
| byte | 8 bit | 0 | +255 |
| ushort | 16 bit | 0 | +65_535 |
| uint | 32 bit | 0 | +4_294_967_295 |
| ulong | 64 bit | 0 | +18_446_744_073_709_551_615 |
Uma variável (ou expressão) de um tipo pode ser convertida facilmente para outro. Por exemplo, em uma operação de atribuição, se o tipo do valor atribuído (lhs) garantir que o valor estará dentro do intervalo do tipo de destino (rhs), basta uma atribuição simples:
uint ui = uint.MaxValue;
ulong ul = ui; // no problem
Por outro lado, se o intervalo do tipo de origem não for um subconjunto do intervalo de valores do destino, é necessário um cast, a operação (), mesmo que o valor específico esteja dentro do intervalo do destino:
short s = 42;
uint ui = (uint)s;
A classe BitConverter oferece uma forma prática de converter tipos inteiros de e para arrays de bytes.
O trabalho no projeto do carro de controle remoto continua. A largura de banda no sistema de telemetria é preciosa, e pediram que você implemente um protocolo de mensagens para comunicar os dados de telemetria.
Os dados são transmitidos em um buffer (array de bytes). Quando inteiros são enviados, o tamanho do buffer é reduzido com o protocolo descrito abaixo.
Cada valor deve ser representado no menor tipo inteiro possível (os tipos byte e sbyte não estão incluídos, pois a economia seria trivial):
| De | Até | Tipo |
|---|---|---|
| 4_294_967_296 | 9_223_372_036_854_775_807 | long |
| 2_147_483_648 | 4_294_967_295 | uint |
| 65_536 | 2_147_483_647 | int |
| 0 | 65_535 | ushort |
| -32_768 | -1 | short |
| -2_147_483_648 | -32_769 | int |
| -9_223_372_036_854_775_808 | -2_147_483_649 | long |
O valor deve ser convertido para o número apropriado de bytes do tipo atribuído a ele. O buffer completo é composto por um byte que indica a quantidade de bytes adicionais no buffer (byte de prefixo) seguido pelos bytes que contêm o inteiro (bytes de payload).
Alguns dos tipos usam um número idêntico de bytes (por exemplo, os tipos uint e int). Normalmente, eles teriam o mesmo byte de prefixo, mas isso tornaria a decodificação problemática. Para contornar isso, o protocolo introduz um pequeno truque: para tipos com sinal, o valor do byte de prefixo é 256 menos o número de bytes adicionais no buffer.
Apenas o byte de prefixo e o número de bytes seguintes indicados pelo prefixo serão enviados na comunicação. Internamente, um buffer de 9 bytes é usado (com zeros à direita, conforme necessário) tanto pelas rotinas de envio quanto pelas de recebimento.
Implemente o método estático TelemetryBuffer.ToBuffer() para codificar um buffer a partir do parâmetro passado para o método.
// Type: ushort, bytes: 2, signed: no, prefix byte: 2
TelemetryBuffer.ToBuffer(5)
// => {0x2, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
// Type: int, bytes: 4, signed: yes, prefix byte: 256 - 4
TelemetryBuffer.ToBuffer(Int32.MaxValue)
// => {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 };
Implemente o método estático TelemetryBuffer.FromBuffer() para decodificar o buffer recebido e retornar o valor na forma de um long.
TelemetryBuffer.FromBuffer(new byte[] {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 })
// => 2147483647
Se o byte de prefixo tiver um valor inesperado, 0 deve ser retornado.
Crie sua conta no Exercism para aprender e dominar C# com 62 conceitos178 exercícios e mentoria humana de verdade, tudo de graça.