In

Inteiros em Rust

1 exercício

Sobre Inteiros

Os inteiros são números sem parte fracionária nem decimal. São representados na máquina como um padrão de bits binários.

Os inteiros podem ou não ter sinal. Ter sinal significa reservar um dos bits do número para indicar se esse número é negativo ou não.

Todos os inteiros têm uma largura em bits, que é apenas o número de bits que compõem esse número. Isto afeta o valor máximo que pode ser representado por esse tipo de inteiro.

Por exemplo, um dos tipos de inteiro mais comuns é o u8: um inteiro sem sinal, de 8 bits. Podes reconhecer este tipo como um único byte. Tem um valor mínimo de 0 e um valor máximo de 255.

O Rust tem 12 tipos primitivos de inteiros, divididos por largura em bits e por sinal:

Sem sinal Com sinal
u8 i8
u16 i16
u32 i32
u64 i64
u128 i128
usize isize

A largura em bits de um inteiro é sempre indicada pelo número que vem depois do u ou do i. usize e isize são especiais: têm a mesma largura que um ponteiro na máquina de destino. Isto significa que, numa arquitetura de 64 bits, usize e isize têm 64 bits de largura, mas, numa arquitetura de 32 bits, têm 32 bits de largura.

Qual devo usar?

Em geral, se só precisares de representar um número, usa um i32: 32 bits têm um intervalo suficientemente amplo para que seja relativamente improvável que ocorra transbordo, e os números com sinal têm menos surpresas do que os números sem sinal. i32 é equivalente a um long em C, ou a um int em Java. Se usares um literal numérico e não anotares explicitamente o tipo, assume i32 por omissão.

Se estiveres a trabalhar com dados binários, o mais fácil é trabalhar com bytes: &[u8] ou Vec<u8>.

O Rust usa usize para tamanhos e indexação de coleções. Isto acontece porque, teoricamente, um computador só consegue endereçar usize::MAX bytes de memória, pelo que não são possíveis coleções maiores em memória. Por isso, usize pode ser útil se trabalhares muito com coleções.

Se os teus dados não couberem num inteiro de 32 bits, considera alargar para um inteiro de 64 ou 128 bits. Se os teus dados não couberem num inteiro de 128 bits, podes usar um tipo de inteiro grande, como o fornecido por num-bigint.

Os inteiros de 16 bits não são muito comuns, mas podem ser úteis quando se programa para certos microcontroladores.

Se sabes que não existem casos negativos válidos para a tua aplicação, é melhor usar um inteiro sem sinal em vez de um inteiro com sinal. Contar é um bom exemplo disso.

Converter entre inteiros

O Rust não tem conversões numéricas implícitas. Se precisares de converter entre tipos de inteiros, existem duas estratégias básicas: a palavra-chave as e os traits From e TryFrom.

Usar a palavra-chave as é simples: expr as Type. No entanto, há uma série de ressalvas e subtilezas que tens de ter em conta quando usas conversões com as.

A conversão baseada em traits é um pouco mais complexa, mas mais segura: os traits de conversão só são implementados onde é seguro. Por exemplo, i32 implementa From<u8>, From<u16>, From<i8> e From<i16>: qualquer valor representável por qualquer um destes tipos tem garantia de ser representável num i32. Pode ser usado como i32::from(expr), ou expr.into(), em que expr corresponde a um desses tipos. i32 também implementa TryFrom<u32>, TryFrom<u64>, TryFrom<u128>, TryFrom<usize>, TryFrom<i64>, TryFrom<i128> e TryFrom<isize>. Estas conversões vão explicitamente ter sucesso ou provocar transbordo, dependendo do valor. Para as usares, tens de importar os traits std::convert::TryFrom ou std::convert::TryInto, conforme apropriado, e depois usar i32::try_from(expr) ou expr.try_into(), em que expr corresponde a um tipo apropriado.

Usar conversão baseada em traits em vez de conversão com as é geralmente preferível, sobretudo quando se converte de um tipo mais largo para um mais estreito. A conversão baseada em traits é insignificantemente mais dispendiosa do que a conversão com as: usar as por motivos de desempenho não vale a pena, exceto num ciclo extremamente crítico.

Editar via GitHub A ligação abre numa nova janela ou separador