Diferença no Output de Função Matemática

1. Diferença no Output de Função Matemática

Luciano Magrini
magriniluciano

(usa Ubuntu)

Enviado em 20/06/2018 - 11:41h

Prezados,
sou iniciante em C e estou tentando "traduzir" um código de C para Python, minha zona de conforto.
Estava comparando as saídas de um e de outro e percebi que estavam bem diferentes apesar de eu ter certeza que os códigos já são equivalentes.
Daí, fui para a velha técnica dos "printfs" em cada linha do código para achar o problema e me deparei com algo bem curioso (pelo menos para mim, que não entendo de C a fundo).

No programa em C faz-se repetidas vezes o cálculo do seno de um certo argumento x da seguinte forma: primeiro se calcula o argumento x (que depende de alguns inputs) e armazena numa variável do tipo float. Na sequência, calcula-se o seno. É como está feito para o "sin1" no código que transcrevo abaixo. Em Python eu fiz o cálculo direto: joguei o argumento x dentro da função seno sem uma variável intermediária. É como está feito para o "sin2" no codigo abaixo. Mas aqui está o problema. Os outputs são muito diferentes (também abaixo) e do ponto de vista matemático o segundo está correto mas o primeiro não. O que pode explicar essa diferença?

Grato a todos.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(){
float sin1, sin2, variable1, variable2;
long i;

for (i = 0; i < 10; i++){
variable1 = 2.0*M_PI*i;
sin1 = sin(variable1);
sin2 = sin(2.0*M_PI*i);
printf("sin1 = %.20g\n", sin1);
printf("sin2 = %.20g\n", sin2);
}

exit(-1);}


Output:
sin1 = 0
sin2 = 0
sin1 = 1.7484555314695171546e-07
sin2 = -2.4492937051703357089e-16
sin1 = 3.4969110629390343092e-07
sin2 = -4.8985874103406714178e-16
sin1 = 4.7699522554012219189e-08
sin2 = -7.3478805861154150927e-16
sin1 = 6.9938221258780686185e-07
sin2 = -9.7971748206813428356e-16
sin1 = -5.5628368045290699229e-07
sin2 = -1.2246467996456086511e-15
sin1 = 9.5399045108024438377e-08
sin2 = -1.4695761172230830185e-15
sin1 = -1.1602668337218347006e-06
sin2 = -1.7145055406796757928e-15
sin1 = 1.3987644251756137237e-06
sin2 = -1.9594349641362685671e-15
sin1 = 1.4309856055660929997e-07
sin2 = -2.2043642817137429346e-15


  


2. Re: Diferença no Output de Função Matemática

Paulo
paulo1205

(usa Ubuntu)

Enviado em 20/06/2018 - 14:09h

Matematicamente, todos esses senos de múltiplos de 2pi deveriam dar zero. Entretanto, por problemas de arredondamento, você nunca tem exatamente um múltiplo de 2pi, mas sim um valor que fica um pouco acima ou um pouco abaixo.

Esse erro de arredondamento fica mais grave quando você usa a variável intermediária, pois você a fez ter tipo float, que tem menor precisão do que a que você tem na multiplicação (cujo tipo implícito deve ser ou double ou long double). Com tal precisão reduzida, os valores de variable1 ficam ainda mais longe dos valores exatos dos múltiplos de 2pi, o que seria suficiente para explicar o maior valor calculado para seus senos.

Você pode experimentar trocar o tipo de todas as variáveis que hoje estão como float para double, para ver se o erro diminui.


3. Re: Diferença no Output de Função Matemática

Luciano Magrini
magriniluciano

(usa Ubuntu)

Enviado em 20/06/2018 - 17:00h

paulo1205 escreveu:

Matematicamente, todos esses senos de múltiplos de 2pi deveriam dar zero. Entretanto, por problemas de arredondamento, você nunca tem exatamente um múltiplo de 2pi, mas sim um valor que fica um pouco acima ou um pouco abaixo.

Esse erro de arredondamento fica mais grave quando você usa a variável intermediária, pois você a fez ter tipo float, que tem menor precisão do que a que você tem na multiplicação (cujo tipo implícito deve ser ou double ou long double). Com tal precisão reduzida, os valores de variable1 ficam ainda mais longe dos valores exatos dos múltiplos de 2pi, o que seria suficiente para explicar o maior valor calculado para seus senos.

Você pode experimentar trocar o tipo de todas as variáveis que hoje estão como float para double, para ver se o erro diminui.


Paulo, obrigado pela explicação.
Troquei, como você sugeriu, float para double, e realmente o erro diminui. Os outputs passam a ser os mesmos.
Obrigado, mesmo!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts