Aritmético inteiro. Divida arredondando o resultado. Parte 1

Quanto mais simples, à primeira vista, a tarefa, menos o desenvolvedor pensa em como implementá-la corretamente, e o erro cometido, na melhor das hipóteses, é descoberto tardiamente, na pior das hipóteses - não é percebido. Será sobre uma dessas tarefas, a saber, divisão fracionária e dimensionamento em controladores que suportam exclusivamente aritmética de número inteiro.

Por que os programadores de aplicativos não prestam atenção aos meandros da computação sob condições dessa aritmética, uma pergunta. Só me atrevo a sugerir que, com toda a probabilidade, o hábito de fazer cálculos na calculadora está afetando ... De qualquer forma, com invejável regularidade, "tenho a felicidade" de ver como os colegas da loja pisam no mesmo rake. Este material visa neutralizar o mesmo "ancinho".

Na aritmética inteira, o resultado da divisão de um inteiro por outro consiste em dois números - o quociente e o restante. Se descartarmos o restante da divisão, obtemos o resultado, em valor absoluto, arredondado para um número inteiro menor.

Realizando cálculos com frações, esse momento é muitas vezes esquecido e, perdidos, eles recebem perdas na precisão dos cálculos. Além disso, a precisão dos cálculos diminui com o aumento do valor do divisor. Por exemplo, que 53/13, que 64/13 resultará em 4, embora, de fato, o quociente da divisão da segunda fração esteja muito mais próximo de 5.
De fato, é simples organizar o arredondamento do resultado para o todo mais próximo. Para fazer isso, basta dobrar o restante da divisão, resumindo-o e dividi-lo novamente pelo mesmo número pelo qual foi inicialmente dividido e adicionar o quociente dessa divisão ao quociente obtido na operação inicial da divisão.
No primeiro exemplo simples, demonstrarei como esse arredondamento é implementado em software usando o exemplo de cálculo da proporção de duas quantidades

Y=k=A/B


Levando em consideração o fato de que tais cálculos no programa podem ser necessários repetidamente, implementamos o algoritmo de cálculo em um formato adequado para compactação em um subprograma.

Para a correta execução dos cálculos intermediários necessários para isso, será necessário um conjunto de cinco registros; Por que cinco e não menos, vou explicar um pouco mais baixo.

Algoritmo de ações:

1. TEMP[2]= A 2. TEMP[3]= B ----- 3. TEMP[0,1]= TEMP[2]/TEMP[3] 4. TEMP[1,2]= TEMP[1]*2 5. TEMP[4]= 0 6. TEMP[1..4]= TEMP[1,2]/TEMP[3,4] 7. TEMP[0]= TEMP[0]+TEMP[1] ----- 8. Y= TEMP[0] 

As etapas 3 a 7 podem ser movidas para uma sub-rotina.

Se desejado, o resultado pode ser gravado diretamente somando TEMP [0] com TEMP [1] fora da sub-rotina de cálculo. Isso não tem princípios. A única coisa a ter em mente é que, com muitos dos mesmos tipos de cálculos, a remoção da operação de adição ao corpo principal do programa pode levar a um aumento na quantidade de memória do programa usada por ele.

Então, por que foram necessários 5 registros para computação intermediária? E a operação de somar o restante da divisão por si só, como mencionado anteriormente, é substituída pela multiplicação do restante por dois? Muito simples - para operar com um conjunto ilimitado de números inteiros.

Deixe-me explicar: se dividirmos, por exemplo, o número 32767 por -32768 no restante, obtemos 32767, e o resultado de sua adição sem dúvida ultrapassará o intervalo do número inteiro.
Ou seja, o restante duplicado de uma divisão inteira de uma fração no interesse de arredondar o resultado dessa divisão deve sempre ser apresentado em formato inteiro duplo.
Para continuar ...

Source: https://habr.com/ru/post/pt412613/


All Articles