Jump to content

Algum problema com biblioteca matematica em C.


Recommended Posts

  • Apoiador Bit

Eu tenho serios problemas com meu GCC ao usar funcoes matematicas. Esse codigo eh um exercicios (13 do capitulo 3) do livro do Andre Backes - Linguagem - Completa e Descomplicada. Como no exemplo abaixo:

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

int main(void) {
  double h, a, b;

  printf("-- Calculo da Hipotenuza do triangulo retangulo --\n");

  scanf("%lf%lf",&a,&b);
  h = sqrt(exp(2.00*log(a) + exp(2.00*log(b))));
 
  printf("O valor da hipotenuza eh: %.4lf\n",h);

  return EXIT_SUCCESS;
}

O problema aparece quando vou compilar, seja usando make ou gcc -std=c??. Tambem usando -std=gnu??

make exec13_3
cc     exec13_3.c   -o exec13_3
/usr/bin/ld: /tmp/ccktALow.o: na função "main":
exec13_3.c:(.text+0x36): referência não definida para "log"
/usr/bin/ld: exec13_3.c:(.text+0x49): referência não definida para "log"
/usr/bin/ld: exec13_3.c:(.text+0x52): referência não definida para "exp"
/usr/bin/ld: exec13_3.c:(.text+0x5c): referência não definida para "exp"
/usr/bin/ld: exec13_3.c:(.text+0x61): referência não definida para "sqrt"
collect2: error: ld returned 1 exit status
make: *** [<builtin>: exec13_3] Error 1

 

Eh nisso que fico perdido. Consultei as headers tgmath.h e math.h, alem de sua indicacao de livro (pdf) "ModernC". Mas nao consigo achar o problema da falta de referencia.

 

PS: sim, a ortografia falha eh por conta do teclado US.

Link to post
Share on other sites
  • Apoiador Bit

Resolvido pessoal.

É com muita vergonha que venho confessar que esquecia de declarar -lm na hora de compilar.

 

Exemplo: gcc exec13_3.c -o exec13_3 -lm

 

#vergonha .

Mas está sanado a dúvida.

Link to post
Share on other sites

Só uma dica com relação ao Teorema de Pitágoras... Ao fazer:

1.png.2e0bf9fde0fef36b2b7c582c78261a59.png

Se a e/ou b forem muito grandes, você poderá obter +INFINTE (overflow) como resposta. A mesma coisa acontece com a exponenciação que você usou...

Uma aproximação melhor e menos provável de obter overflow é selecionando o maior dos dois valores (suponha: a) e fazer:

2.png.7c9a78bf23f98eaf628aa935b896aa25.png

Desde que a != 0 (neste caso h=|b|). Eis a simplificação:

3.png.5abf7ade25f4da89c4bd3739b00ed0d9.png

Assim, (b/a)², no máximo, será um valor subnormal (entre 0 e 1) e a podera ser bem mais próximo do máximo valor suportado da precisão do tipo em ponto flutuante. Além de diminuir o esforço ao calcular apenas uma potência simples.

4.png.04340b59cdae01991bf8e09106b2a120.png

A função:
 

#include <math.h>
 
#define swap(a,b) \
  { double t; t = (a); (a) = (b); (b) = t; }
 
double hipotenuse(double a, double b)
{
  double tmp;

  if ( isnan(a) || isnan(b) ) return NAN;
  if (b > a) swap( a, b );
  if (a < 0.0) return NAN;
  if ( a == 0.0 ) return fabs(b);
  // Poderíamos usar 'return -b' porque b pode ser igual a 0.0, o que resultaria em -0.0,
  // que, para todos os efeitos, é a mesma coisa que +0.0.

  tmp = b / a; 
  return a * sqrt(1.0 + tmp*tmp);
}

 

Edited by fredericopissarra
Link to post
Share on other sites

Regra geral: TODA equação, ao ser codificada usando ponto flutuante, tem que ser condicionada para evitar condições de overflow e underflow... É bom lembrar que tipos em ponto flutuante têm menor precisão binária que os mesmos tipos, do mesmo tamanho, inteiros e que o domínio da representação desses valores (em ponto flutuante) não são ℝ, mas sim ℚ (domínio dos "racionais" -- o que, se pensar bem, é óbvio).

Sobre a alegação de precisão menor... O tipo long long int tem 63 bits de precisão (1 para o sinal), enquanto double tem 53 -- a estrutura de ambos os tipos e de 64 bits. A mesma coisa acontece com int e float (31 e 24, respectivamente). "Precisão" NÃO se refere à quantidade de "algarismos depois da vírgula"...

Edited by fredericopissarra
Link to post
Share on other sites
  • Apoiador Bit
Em 21/01/2021 em 11:44, fredericopissarra disse:

Regra geral: TODA equação, ao ser codificada usando ponto flutuante, tem que ser condicionada para evitar condições de overflow e underflow... É bom lembrar que tipos em ponto flutuante têm menor precisão binária que os mesmos tipos, do mesmo tamanho, inteiros e que o domínio da representação desses valores (em ponto flutuante) não são ℝ, mas sim ℚ (domínio dos "racionais" -- o que, se pensar bem, é óbvio).

Sobre a alegação de precisão menor... O tipo long long int tem 63 bits de precisão (1 para o sinal), enquanto double tem 53 -- a estrutura de ambos os tipos e de 64 bits. A mesma coisa acontece com int e float (31 e 24, respectivamente). "Precisão" NÃO se refere à quantidade de "algarismos depois da vírgula"...

Obrigado pela dica. Aliás, depois de ler, fui conferir a biblioteca <math.h> e sim, as funções estão definidas com double.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...