Trilhas
/
C#
C#
/
Exercícios
/
Telemetria hiperotimizada
Telemetria hiperotimizada

Telemetria hiperotimizada

Exercício de aprendizagem

Introdução

Números inteiros

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;

Conversão de bits

A classe BitConverter oferece uma forma prática de converter tipos inteiros de e para arrays de bytes.

Instruções

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.

1. Codifique um valor inteiro pronto para enviar

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 };

2. Decodifique um buffer recebido

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.

Editar via GitHub O link abre em uma nova janela ou aba
C# Exercism

Tudo pronto para começar Telemetria hiperotimizada?

Crie sua conta no Exercism para aprender e dominar C# com 62 conceitos178 exercícios e mentoria humana de verdade, tudo de graça.