2.1.4 Exercício Estendido: Aritmética de Intervalos
Alyssa P. Hacker está projetando um sistema para ajudar pessoas a resolver problemas de engenharia. Um recurso que ela quer fornecer em seu sistema é a capacidade de manipular quantidades inexatas (como parâmetros medidos de dispositivos físicos) com precisão conhecida, de modo que quando os cálculos são feitos com tais quantidades aproximadas, os resultados ser ão números de precisão conhecida.
Engenheiros elétricos usarão o sistema de Alyssa para calcular quantidades elétricas. Às vezes é necessário para eles calcular o valor de uma resistência equivalente paralela Rp de dois resistores R1 e R2 usando a fórmula:
Os valores de resistência geralmente são conhecidos apenas até alguma tolerância garantida pelo fabricante do resistor. Por exemplo, se você comprar um resistor rotulado "6.8 ohms com 10% de tolerância", você só pode ter certeza de que o resistor tem uma resistência entre 6.12 e 7.48 ohms. Assim, se você tiver um resistor de 6.8 ohms com 10% de tolerância em paralelo com um resistor de 4.7 ohms com 5% de tolerância, a resistência da combinação pode variar de cerca de 2.58 ohms (se os dois resistores estiverem nos limites inferiores) a cerca de 2.97 ohms (se os dois resistores estiverem nos limites superiores).
A ideia de Alyssa é implementar "aritmética de intervalos" como um conjunto de operações aritméticas para combinar "intervalos" (objetos que representam o intervalo de valores possíveis de uma quantidade inexata). O resultado de adicionar, subtrair, multiplicar ou dividir dois intervalos é em si um intervalo, representando o intervalo do resultado.
Alyssa postula a existência de um objeto abstrato chamado "intervalo" que tem dois pontos extremos: um limite inferior e um limite superior. Ela também presume que, dados os pontos extremos de um intervalo, ela pode construir o intervalo usando o construtor de dados make_interval. Alyssa primeiro escreve uma função para adicionar dois intervalos. Ela raciocina que o valor mínimo que a soma poderia ser é a soma dos dois limites inferiores e o valor máximo que poderia ser é a soma dos dois limites superiores:
Alyssa também calcula o produto de dois intervalos encontrando o mínimo e o máximo dos produtos dos limites e usando-os como os limites do intervalo resultante:
Para dividir dois intervalos, Alyssa multiplica o primeiro pelo recíproco do segundo. Observe que os limites do intervalo recíproco são o recíproco do limite superior e o recíproco do limite inferior, nessa ordem:
Exercício 2.7
O programa de Alyssa está incompleto porque ela não especificou a implementação da abstração de intervalo. Defina os seletores upper_bound e lower_bound para completar a implementação.
💡 Mostrar solução — tente primeiro!💡 Esconder solução
Com make_interval construindo o par na ordem (inferior, superior), os seletores são diretos:
function lower_bound(i) {
return head(i);
}
function upper_bound(i) {
return tail(i);
}
(Se quiséssemos aceitar argumentos em qualquer ordem, bastaria math_min/math_max dos dois componentes — mas a convenção do construtor torna isso desnecessário.)
Exercício 2.8
Usando um raciocínio análogo ao de Alyssa, descreva como a diferença de dois intervalos pode ser calculada. Defina uma função correspondente chamada sub_interval.
💡 Mostrar solução — tente primeiro!💡 Esconder solução
Raciocínio. O menor valor da diferença ocorre com o menor e o maior ; o maior, com o maior e o menor :
Equivalente a somar com o intervalo negado — repare a troca dos extremos, o detalhe de que o exercício trata.
Exercício 2.9
A largura de um intervalo é metade da diferença entre seus limites superior e inferior. A largura é uma medida da incerteza do número especificado pelo intervalo. Para algumas operações aritméticas, a largura do resultado de combinar dois intervalos é uma função apenas das larguras dos intervalos argumentos, enquanto para outras a largura do intervalo resultado da combinação não é uma função das larguras dos intervalos argumentos. Mostre que a largura da soma (ou diferença) de dois intervalos é uma função apenas das larguras dos intervalos sendo adicionados (ou subtraídos). Dê exemplos para mostrar que isso não é verdadeiro para multiplicação ou divisão.
💡 Mostrar solução — tente primeiro!💡 Esconder solução
Soma: com , ,
e a subtração é idêntica (os extremos trocados não mudam a diferença). A largura do resultado depende só das larguras.
Multiplicação não: dois pares de intervalos com as mesmas larguras produzem larguras de produto diferentes —
tem largura 2, enquanto tem largura 10 — larguras de entrada iguais, saídas diferentes. Logo a largura do produto (e da divisão, que multiplica pelo recíproco) depende também da posição dos intervalos, não apenas das larguras.
Exercício 2.10
Ben Bitdiddle, um especialista programador, observa que não faz sentido dividir por um intervalo que abrange zero. Modifique o código de Alyssa para verificar essa condição e sinalizar um erro se isso ocorrer.
💡 Mostrar solução — tente primeiro!💡 Esconder solução
Um intervalo "atravessa zero" quando — dividir por ele não faz sentido (o recíproco explode):
A segunda chamada dispara o erro — execute e veja.
Exercício 2.11
Em passando por esse código, Ben também observa que é possível melhorar a eficiência de mul_interval usando o fato de que os pontos extremos dos intervalos são números. Mostre que existem nove casos para computar o produto de dois intervalos com base nos sinais dos pontos extremos, e reescreva mul_interval para levar vantagem disso.
💡 Mostrar solução — tente primeiro!💡 Esconder solução
Cada extremo pode ser negativo ou não-negativo; classificando os dois intervalos pelos sinais de há combinações — e em oito delas os extremos do produto são conhecidos de antemão. Só quando ambos atravessam zero é preciso comparar produtos:
Se vale a pena? Ben ganharia duas multiplicações ao custo de uma pirâmide de testes — o próprio livro sugere ceticismo com "otimizações" assim.
Exercício 2.12
Defina um construtor make_center_percent que recebe um centro e uma tolerância percentual e produz o intervalo desejado. Você também deve definir um seletor percent que produz a tolerância percentual para um dado intervalo.
O Problema da Dependência
Ao explorar mais profundamente o sistema, você descobrirá que diferentes expressões algébricas que são matematicamente equivalentes podem produzir intervalos de resultados diferentes quando implementadas na aritmética de intervalos. Por exemplo, duas fórmulas para calcular resistências paralelas:
function par1(r1, r2) {
return div_interval(mul_interval(r1, r2),
add_interval(r1, r2));
}
function par2(r1, r2) {
const one = make_interval(1, 1);
return div_interval(one,
add_interval(div_interval(one, r1),
div_interval(one, r2)));
}
Essas duas funções produzem resultados diferentes! Isso ocorre porque a aritmética de intervalos trata cada ocorrência de uma variável como uma quantidade independente, levando a resultados mais imprecisos quando uma variável aparece várias vezes em uma expressão. Este é o problema da dependência na aritmética de intervalos.
Exercícios 2.13-2.16
Os exercícios restantes exploram mais profundamente este problema da dependência, derivando fórmulas para tolerância percentual em produtos, investigando por que par2 produz resultados melhores que par1, e explorando se é possível projetar um sistema de aritmética de intervalos que evite completamente esse problema.
💡 Mostrar solução — tente primeiro!💡 Esconder solução
A tolerância percentual é só a largura relativa ao centro; os resistores de "6,8 kΩ com 10%" do texto viram [6.12, 7.48]. (Para centros negativos seria preciso um math_abs no percent — os resistores do livro, felizmente, são positivos.)
📝 Encontrou algo errado nesta página?
Sua ajuda é muito importante para melhorar a qualidade da tradução!
🐛 Encontrou um erro?
Se você encontrou:
- Erro de tradução (palavra incorreta, termo técnico errado)
- Erro de ortografia ou gramática
- Link quebrado
- Código de exemplo que não funciona
- Problema de formatação
❓ Tem uma dúvida?
Se você tem:
- Dúvida sobre o conteúdo desta seção
- Pergunta sobre um conceito do SICP
- Dificuldade em entender algum exemplo
- Questão sobre a tradução de algum termo
💡 Tem uma sugestão de melhoria?
Se você quer sugerir:
- Melhoria na explicação
- Exemplo adicional
- Recurso visual (diagrama, ilustração)
- Qualquer outra ideia
🌍 Quer discutir a tradução?
Se você quer debater:
- Escolha de tradução de algum termo
- Consistência de terminologia
- Nuances do português
Obrigado por ajudar a melhorar o SICP.js PT-BR! ✨