Questão 7 (Exercício de Programação). Admita:
\beta=10, t=3, \ell=-5, \mu=5 .
Sugira um código para truncamento e um código para arredondamento, considerando que o número x seja representado por uma quantidade j de dígitos, com
a) j \leq t
b) j>t

Passo 1

O enunciado dá os parâmetros do formato de ponto-flutuante:
\beta=10, \;t=3, \;\ell=-5, \;\mu=5.
Pede-se: sugerir um código (algoritmo) para realizar
  • truncamento, e
  • arredondamento,
    quando um número x é representado por j dígitos da mantissa, nos dois casos:
    a) j \le t (ou seja, já cabe na precisão),
    b) j > t (ou seja, precisa reduzir para t dígitos).
Informações relevantes que vamos usar (tudo extraído do enunciado ou necessário para resolver):
  • Base do sistema: \beta=10.
  • Precisão desejada: \;t=3 dígitos significativos.
  • Limites de expoente: \ell=-5 (mínimo) e \mu=5 (máximo) — importantes para detectar underflow/overflow se o arredondamento alterar o expoente.
  • Representação canônica assumida: um número normalizado é representado por sinal s\in\{+1,-1\}, vetor de dígitos da mantissa (d_1,d_2,\dots,d_j) com 1\le d_1\le \beta-1, expoente e e
x = s\cdot (d_1.d_2d_3\ldots d_j)_{\beta}\cdot \beta^{e}.
  • A variável j é o número atual de dígitos disponíveis na mantissa de x.
O objetivo técnico: fornecer pseudocódigo claro e robusto para os dois procedimentos (truncamento e arredondamento), tratando separadamente j\le t e j>t, incluindo tratamento de carry no arredondamento e verificação de limites de expoente ( \ell,\mu).

Passo 2

Entender o que significa cada operação (aula rápida e intuitiva):
Truncamento:
  • Significa simplesmente cortar (descartar) todos os dígitos além do t-ésimo, sem alterar os dígitos mantidos. Ex.: em base \beta=10, com t=3, (1.23456)_{10} truncado para t=3 (1.234)_{10}.
Arredondamento (regra usual “arredondar para o mais próximo”):
  • Olha-se o dígito imediatamente após o t-ésimo (ou seja, d_{t+1}).
  • Se d_{t+1} < \beta/2 então mantém-se os primeiros t dígitos (igual ao truncamento).
  • Se d_{t+1} > \beta/2 então incrementa-se o t-ésimo dígito em 1 (com propagação de carry se necessário).
  • Se d_{t+1} = \beta/2 a regra mais comum é arredondar para par ou simplesmente arredondar para cima (aqui usaremos a regra simples: arredondar para cima quando d_{t+1}\ge \beta/2). Em \beta=10, o limiar é 5.
Efeito de carry no arredondamento:
  • Se após incrementar o dígito d_t ele fica igual a \beta, então esse dígito vira 0 e propagamos 1 para d_{t-1}, etc.
  • Se todos os dígitos até d_1 causarem carry (ex.: (9,9,9) incrementando), obtemos uma situação como (\beta,0,0,\ldots) — normalizamos transformando isso em (1,0,0,\ldots) e incrementamos e em 1. Isso pode causar overflow se e>\mu.
Underflow/Overflow:
  • Se o incremento do expoente fizer e>\mu reportar overflow (p.ex. representar como ±infinito no sistema).
  • Se a operação resultasse em expoente <\ell (pouco provável apenas por truncamento, mas pode ocorrer em representações subnormais), teria underflow. Aqui vamos apenas sinalizar se ocorrer.

Passo 3

Caso geral j \le t (não é preciso reduzir):
  • Explicação: se o número já tem no máximo t dígitos significativos, tanto truncamento quanto arredondamento deixam os dígitos iguais (podemos opcionalmente preencher zeros até t para padronizar a mantissa).
  • Código (ideia): retornar os dígitos originais (ou os mesmos dígitos com zeros à direita até completar t).
  • Exemplo simples: t=3, se x = (+, (1,2), e) com j=2, então resultado será (+,(1,2,0),e) se quisermos t dígitos explícitos.
Passo prático (pseudocódigo explicado em palavras):
  • Se j \le t então
    • para truncamento: devolver mantissa (d_1,\dots,d_j,0,\dots,0) (com zeros até t dígitos) e expoente e.
    • para arredondamento: fazer o mesmo (não há dígito d_{t+1} para decidir mudança).

Passo 4

Caso j > t — algoritmo do truncamento (passo a passo didático e código):
Lógica:
  • Mantemos os primeiros t dígitos (d_1,\dots,d_t).
  • Discardamos (d_{t+1},\dots,d_j).
  • O expoente e não muda.
  • Não há carry a propagar porque não incrementamos nada.
  • Verificação simples: depois do truncamento, a mantissa ainda está normalizada (pois d_1 era não nulo e permanece).
Pseudocódigo (estilo Python-like, com variáveis matemáticas em destaque):
Truncamento:
function TRUNCATE(sign, digits, exponent, \;t, \beta):
# digits é lista (d_1,\dots,d_j) com j= len(digits)
if len(digits) \le \;t:
return (sign, digits padded with zeros to length \;t, exponent)
else:
new_digits = first \;t entries of digits # keep (d_1,\dots,d_t)
return (sign, new_digits, exponent)
Explicação de cada linha:
  • “padded with zeros” significa acrescentar zeros à direita para que a mantissa tenha exatamente t dígitos.
  • “first \;t entries” é a operação de cortar.

Passo 5

Caso j > t — algoritmo do arredondamento (passo a passo didático e código):
Lógica:
  1. Olhar o dígito seguinte d_{t+1}.
  2. Se d_{t+1} < \beta/2 então o resultado é igual ao truncamento.
  3. Se d_{t+1} \ge \beta/2 então incrementamos d_t em 1 e realizamos a propagação de carry para a esquerda até que não haja mais carry ou até atingir d_1.
  4. Se a propagação provoca um overflow nos dígitos (isto é, além de d_1 ainda há carry), então transformamos a mantissa em (1,0,0,\dots,0) (com t dígitos: 1 seguido de t-1 zeros) e fazemos e \leftarrow e + 1.
  5. Após possível incremento do expoente, verificar limites: se e>\mu sinalizar overflow; se e<\ell sinalizar underflow (se houver redução do expoente, o que normalmente só ocorre em casos especiais).
Pseudocódigo (com detalhes de carry e verificações):
function ROUND(sign, digits, exponent, \;t, \beta, \ell, \mu):
j = len(digits)
if j \le \;t:
# não há dígito extra para decidir arredondamento
return (sign, digits padded with zeros to length \;t, exponent)
# j > t
prefix = first \;t digits of digits # (d1,…,dt)
next_digit = digits[ \;t] # d_{t+1}, index baseado em 0 em pseudocódigo
if next_digit < floor( \beta/2):
return (sign, prefix, exponent) # igual ao truncamento
else:
# devemos incrementar prefix como um inteiro em base beta
i = \;t - 1 # índice do último dígito em prefix (0-based)
carry = 1
while i >= 0 and carry == 1:
prefix[i] = prefix[i] + 1
if prefix[i] == \beta:
prefix[i] = 0
carry = 1
i = i - 1
else:
carry = 0
if carry == 1:
# houve overflow nos dígitos: mantissa vira 1.000… e expoente aumenta
prefix = [1] + [0]*( \;t-1)
exponent = exponent + 1
if exponent > \mu:
signal overflow and return representation inf (segundo convenção)
return (sign, prefix, exponent)
Notas didáticas:
  • Em \beta=10, \beta/2 = 5. Assim, se d_{t+1}\ge 5 arredondamos para cima.
  • O laço while implementa a propagação do carry. Se todos os dígitos se tornarem zero por causa do carry, criamos a mantissa normalizada (1,0,\dots,0) e incrementamos e.

Passo 6

Exemplos numéricos (para fixar): usando \beta=10, \;t=3
Exemplo A (truncamento simples):
  • x = +(1.23456)_{10}\cdot 10^{2}. Aqui j=5>t=3.
  • TRUNCATE: mantissa fica (1,2,3) +(1.23\underline{4}) com t=3 interpretado como 1.234\cdot10^{2} (ou padronizando: 1.234 com três dígitos fracionários? manter consistência: mantissa (1,2,3) significa 1.23 se interpretarmos duas casas fracionárias; atenção: estamos usando o formato d_1.d_2d_3 então o valor é 1.234\cdot10^{2} se os dígitos originais foram 1,2,3,4,5 — a ideia é cortar após 3 dígitos mantidos).
Exemplo B (arredondamento com carry):
  • x = +(1.23456)_{10}\cdot 10^{2}. d_{4}=5\ge 5 então incrementa d_3 de 4 para 5. Resultado: +(1.235)\cdot10^{2}.
  • Caso crítico: x = +(9.9956)_{10}\cdot 10^{2} com t=3. Prefixo (9,9,9), próximo dígito 5\ge 5. Incrementar (9,9,9) produz carry até além de d_1, transformando prefixo em (1,0,0) e expondo e \leftarrow e+1. Portanto o número arredondado fica +(1.000)\cdot10^{3} (e verificar se e+1 não excede \mu).

Resposta

Truncamento (pseudocódigo):
function TRUNCATE(sign, digits, exponent, \;t, \beta):
j = len(digits)
if j \le \;t:
return (sign, digits + [0]*( \;t-j), exponent)
else:
new_digits = digits[0: \;t] # keep (d_1,…,d_t)
return (sign, new_digits, exponent)
Arredondamento (pseudocódigo):
function ROUND(sign, digits, exponent, \;t, \beta, \ell, \mu):
j = len(digits)
if j \le \;t:
return (sign, digits + [0]( \;t-j), exponent)
prefix = digits[0: \;t] # (d_1,…,d_t)
next_digit = digits[ \;t] # d_{t+1}
if next_digit < floor( \beta/2):
return (sign, prefix, exponent)
else:
i = \;t - 1
carry = 1
while i >= 0 and carry == 1:
prefix[i] = prefix[i] + 1
if prefix[i] == \beta:
prefix[i] = 0
carry = 1
i = i - 1
else:
carry = 0
if carry == 1:
prefix = [1] + [0]
( \;t-1)
exponent = exponent + 1
if exponent > \mu:
signal overflow (represent as ±inf or conforme ao sistema)
return (sign, prefix, exponent)

Exercícios relacionados