Ir ao conteúdo

Posts recomendados

Postado

Dentro de um programa que eu fiz, tem um detalhe que está me incomodando. Existe um vetor de inteiros que em determinado momento eu preciso multiplicar um de seus valores por 1.2. Quando eu faço isso dessa forma, quando o valor do vetor é 10, por exemplo:

ataque1[i] = 1.2*ataque1[i];

O resultado sempre sai 1 abaixo do esperado. No caso, a multiplicação de 1.2*10 dá 11 como resultado. Quando eu faço com 30, dá 35 ao invés de 36, etc.

Quando eu faço da seguinte forma:

ataque1[i] = 12*ataque1[i]/10;

O resultado dá certo. 12, quando ataque1 é 10, por exemplo.

Eu imagino que seja algum problema por estar multiplicando um float (1.2) por uma variável do tipo inteiro. Se alguém puder me ajudar, eu agradeceria.

  • Curtir 1
Postado

Deu certo dessa forma. Mas não entendi muito bem o porquê. Quando não se especifica os tipos, o compilador meio que modifica um pouco os valores para realizar operações de tipos diferentes?

  • Curtir 1
Postado

Não consegui reproduzir seus resultados...

 

Testei com esse código:

#include <stdio.h>

int main()
{
    int a[2] = {10, 30};
    a[0] = 1.2 * a[0];
    a[1] = 1.2 * a[1];
    printf("%d %d\n", a[0], a[1]);

    return 0;
}

E os resultados foram:

12 36

 

Talvez seja diferença de compilador? Fazendo esse teste no seu ocorre o mesmo problema?

  • Curtir 2
Postado

Acabei de fazer um programa igual ao seu. Tentei já inicializando o vetor de inteiros com 10 e 30 e depois tentei pedindo o valor ao usuário. Em ambos os casos o resultado foi 11 e 35, e eu não faço ideia o porquê haha.

  • Curtir 1
Postado

Testei o mesmo código em outro compilador e deu 11 e 35.

 

E descobri porque acontece...

 

O problema é que 1.2 dá dízima periódica na forma binária, ficando:

(1.2)10 = (1.00110011001100110011...)2

 

Então surge um problema de arredondamento... Veja, convertendo o número binário com 20 casas após a vírgula para decimal resulta em:

 

(1.00110011001100110011)2   =>>>   (1.19999980926513671875)10

 

Se multiplicar isto por 10 obterá:

 

11.9999980926513671875

 

E separando apenas a parte inteira desse número você obtém 11, ao invés de 12 como esperado.

 

 

Então o arredondamento muda dependendo em que posição da dízima você para...

 

Nesse caso a multiplicação com 1.2 como double (que é como a constante é interpretada quando nenhum tipo é especificado) acaba arredondando para baixo.

 

Ou seja, contrariamente ao esperado nesse caso a maior precisão do double resulta em um resultado errado, enquanto com float é arrendado para cima resultando no valor correto. Mas observe que isso poderia mudar se fosse outro número racional com dízima na forma binária, pois em outro caso o double poderia ser arredondado corretamente e o float de modo errado dependendo em que posição do número na forma binária o valor para de ser armazenado nesses tipos de variáveis...

 

Como garantir que isso não aconteça? Você pode fazer contas apenas com números inteiros, como você fez, ou então usar uma função para sempre obter o valor do teto do número de ponto flutuante (ceil() da biblioteca math.h) antes de armazenar na variável inteira.

  • Curtir 2
Postado

Isrnick, muito bom. Eu acho que eu nunca imaginaria isso como o problema, então obrigado haha.

 

E vangodp, valeu também pela explicação, agora entendi melhor.

 

Obrigado pelos dois pela ajuda :)

  • Curtir 1
Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...