Função acos retorno nan [RESOLVIDO]

1. Função acos retorno nan [RESOLVIDO]

Samuel Leonardo
SamL

(usa XUbuntu)

Enviado em 31/07/2014 - 09:33h

Por quê a função acos retorna nan quando eu passo o cosseno igual 1 entre dois vetores? Não era para simplesmente retornar zero?

Isso acontece quando tento calcular o cosseno entre dois vetores e os vetores estão um sobre o outro, em qualquer quadrante ocorre retorno nan, só precisa mesmo que os vetores estejam sobrescritos.

Edit:
Para exemplificar, mostro abaixo dois vetores que quando calculado o cosseno deles e com ele usado em acos retorna nan:

typedef struct
{
float x, y;
} Vector2;

float length ( Vector2 v )
{
return sqrt(v.x * v.x + v.y * v.y);
}

float cos_theta ( Vector2 a, Vector2 b )
{
return (a.x * b.x + a.y * b.y) / (length(a) * length(b));
}
Vector2 a = {-45, -45};
Vector2 b = {-80, -80};
// calcula o cosseno do angulo de a e b
float c = cos_theta(a, b);

// agora calcula o arco cosseno e vai retornar nan
printf("acos(c) = %f\n", acos(c));





  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 31/07/2014 - 15:53h

Seu conserto está ou no lugar errado ou de um jeito errado.

Dentro da função cos_theta(), em lugar de isnan(), o certo seria você fazer dois testes:

1) se o denominador vale zero (nesse caso, você provavelmente vai querer, sim, retornar NaN);

2) se o valor calculado da fração é, por problemas de arredondamento, maior do que 1 ou menor que -1, para que você retorne um valor dentro da faixa aceitável.

3. Re: Função acos retorno nan [RESOLVIDO]

Ton Melo
IZhaq_melo

(usa FreeBSD)

Enviado em 31/07/2014 - 10:34h

Sam L. escreveu:

Por quê a função acos retorna nan quando eu passo o cosseno igual 1 entre dois vetores? Não era para simplesmente retornar zero?

Isso acontece quando tento calcular o cosseno entre dois vetores e os vetores estão um sobre o outro, em qualquer quadrante ocorre retorno nan, só precisa mesmo que os vetores estejam sobrescritos.


voce tem o código que ta dando esse retorno?


4. Re: Função acos retorno nan [RESOLVIDO]

Ton Melo
IZhaq_melo

(usa FreeBSD)

Enviado em 31/07/2014 - 11:34h

Sam L. escreveu:

Eu editei meu primeiro post e coloquei todo o código que uso para calcular o ângulo entre dois vetores.

Eu imprimi a saída do calculo do cosseno (float c = cos_tetha(a,b)) dos dois vetores e mostrar um número como: 1.000000000511063191765970259439

Pelo visto é algum problema com arredondamento.


ta vamos com calma..

1º a máquina que voce ta executando isso é 64 ou 32 bits? não sei se voce sabe mas os tipos de dados são indexados de acordo com a palavra da máquina, exemplo um dispositivo arm com um linux tem o mesmo Float que um PC ou mesmo um Server 64 bits?? não né!

2º voce escolheu um tipo de dado com precisão básica( FLOAT )
tem a precisao de: -3.4E- 38 a 3.4E+38

se voce quer mais precisa use o Double: - 1.7 E-308 a 1.7 E+308

com o dobro de Bytes para o armazenamento creio que de pra suprir os seus cálculos.

fonte: http://pt.kioskea.net/faq/10173-linguagem-c-tipos-de-dados
https://en.wikipedia.org/wiki/C_data_types
http://tsiad.ifsul.edu.br/moodle/conteudo/modulo1/lop/lop_ug/at2/02.pdf

se mesmo assim não for suficiente.. não use o long double do c ele so aceita valores positivos.

se tudo que eu disse não for o suficiente..
voce vai ter que usar a linguagem de programação que os físicos usam FORTRAN ( 95 )

veja os tipos de dados:
http://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vn6o/index.html

veja a comparação o

double do C tem 4 Bytes de precisão
o Double do Fortran tem de 4 a 32 Bytes de precisão

espero ter ajudado.


5. Re: Função acos retorno nan [RESOLVIDO]

Thiago Henrique Hüpner
Thihup

(usa Manjaro Linux)

Enviado em 31/07/2014 - 12:17h

Nao sei se isso vai te ajudar , mas nas minhas pesquisas sobre a math.h eu vi isso :

" double acos (double x);
float acosf (float x);
long double acosl (long double x);"

Para usar o acos tem que ser double;
Para usar o acosf tem que ser float;
Para usar o acosl tem que ser long double;

Espero que isso ajude em algo

E na função cos_theta tente usar + parenteses,pode ser isso

T+


6. Re: Função acos retorno nan [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 31/07/2014 - 16:45h

IZhaq_melo escreveu:

ta vamos com calma..

1º a máquina que voce ta executando isso é 64 ou 32 bits? não sei se voce sabe mas os tipos de dados são indexados de acordo com a palavra da máquina, exemplo um dispositivo arm com um linux tem o mesmo Float que um PC ou mesmo um Server 64 bits?? não né!


Errado. Ponto flutuante não tem necessariamente a ver com arquitetura. Alguns processadores mais simples só trabalham com inteiros, e toda a representação de FP é feita em software.

Apesar disso, existem representações padronizadas de FP, como a IEEE-754, que podem ser implementadas em hardware ou por software e que funcionam de modo idêntico em qualquer dessas implementações. Para você ter uma ideia, desde o tempo dos XTs de 16bits com MS-DOS, desde que equipados com coprocessador matemático 8087, os PCs comuns já podiam se servir do formato IEEE-754, que é o mesmo que se usa, hoje, quase universalmente.

2º voce escolheu um tipo de dado com precisão básica( FLOAT )
tem a precisao de: -3.4E- 38 a 3.4E+38

se voce quer mais precisa use o Double: - 1.7 E-308 a 1.7 E+308

com o dobro de Bytes para o armazenamento creio que de pra suprir os seus cálculos.

fonte: http://pt.kioskea.net/faq/10173-linguagem-c-tipos-de-dados
https://en.wikipedia.org/wiki/C_data_types
http://tsiad.ifsul.edu.br/moodle/conteudo/modulo1/lop/lop_ug/at2/02.pdf


Usar mais bits de precisão não necessariamente elimina erros de arredondamento: geralmente só os empurra algumas casas mais para a direita.

se mesmo assim não for suficiente.. não use o long double do c ele so aceita valores positivos.


Viajou!!

se tudo que eu disse não for o suficiente..
voce vai ter que usar a linguagem de programação que os físicos usam FORTRAN ( 95 )


Não muda nem uma letra das considerações acima.

Você deveria saber que Informática não é mágica. Far-lhe-ia muito bem estudar uma disciplina chamada "Cálculo Numérico".

veja os tipos de dados:
http://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vn6o/index.html

veja a comparação o

double do C tem 4 Bytes de precisão
o Double do Fortran tem de 4 a 32 Bytes de precisão


De onde você tirou isso? Errou na terminologia, nas considerações sobre C e nos comentários sobre Fortran.

Na terminologia, não é adequado chamar qualquer representação numérica em ponto flutuante de "double". Só faz sentido falar em "double" se existir uma representação "single". No C, o "single" tem o nome "float" e o "double", não por acaso, tem o nome "double". No Fortran, o "single" é chamado de "REAL" e o "double" é o "DOUBLE PRECISION".

O C não indica valores exatos de precisão para float, double ou long double, mas diz que a representação de long double deve ser maior que ou igual à de double, que deve ser maior que ou igual à de float. Se são maiores ou meramente iguais, e qual o tamanho de cada uma, depende da arquitetura e de escolhas feitas pelo compilador. Nos nossos PCs e em outras máquinas com IEEE-754, todos os compiladores usam 4 bytes para float e oito para double. Quanto a long double, o GCC usa a representação da Intel com 10 bytes, ao passo que o Visual Studio o trata, por default, de modo idêntico a double.

Do mesmo modo que o C, o padrão do Fortran não determina representações internas a serem uadas pelas implementações. Na prática, porém, acontece o mesmo que se faz com C ou qualquer outra linguagem: mapeiam-se os tipos da linguagem ou nos tipos nativos da arquitetura ou em algo provido em software por alguma biblioteca, preferencialmente de acordo com padrões. Tipicamente, nos nossos PCs e outras máquinas com IEEE-754, REAL vira sinônimo de REAL*4, e DOUBLE PRECISION equivale a REAL*8.

O documento que você indicou como referência para o Fortran se refere, na verdade, a uma implementação específica. Ao contrário do que você sugere, ele não lista em momento algum um "REAL*32" (que você chamou de "double de 32 bytes"). 32 bytes só aparecem como opção para o tipo COMPLEX (que é a justaposição de dois valores do tipo REAL, para representar a parte real e a parte imaginária de um número complexo). No caso de COMPLEX*32, o que se tem é a justaposição de dois REAL*16. Além disso, o documento deixa muito claro que tanto REAL*16 quanto COMPLEX*32 só estão disponíveis em uma plataforma específica (o mesmo compilador, quando direcionado a outra plataforma, não conta com tais tipos), de modo que é um erro você generalizar tais representações como sendo "do Fortran".

Representações arbitrárias de compiladores específicos existem em qualquer linguagem, não só em Fortran. O GCC, por exemplo, tem, em algumas arquiteturas (incluindo Intel-32 e AMD64, dos nossos PCs), tipos não-padronizados pela linguagem, tais como _float128 (128 bits, ou 16 bytes). Não sei detalhes de como ele representa tais números nem de como opera com eles, mas quase certamente o faz por software, dado que os processadores dos nossos PCs não têm nativamente uma implementação de números de ponto flutuante com mais de 80 bits. A nova versão do IEEE-754, de 2008 (a versão original era de 1985), define um tipo de ponto flutuante de 128 bits, mas quase nenhum processador existente hoje tem suporte nativo a ela.

Por fim, considere ainda que Fortran não necessariamente é "A" resposta para qualquer programa que toque em Matemática. As versões de 1999 e de 2011 do padrão da linguagem C procuraram (a meu ver, sem a menor necessidade, até porque eu não tenho nada contra o uso de múltiplas linguagens para diferentes domínios de problemas) inserir nela muitos recursos de computação numérica, provavelmente inspirados em Fortran.


7. Re: Função acos retorno nan [RESOLVIDO]

Ton Melo
IZhaq_melo

(usa FreeBSD)

Enviado em 01/08/2014 - 10:03h

paulo1205 escreveu:

IZhaq_melo escreveu:

ta vamos com calma..

1º a máquina que voce ta executando isso é 64 ou 32 bits? não sei se voce sabe mas os tipos de dados são indexados de acordo com a palavra da máquina, exemplo um dispositivo arm com um linux tem o mesmo Float que um PC ou mesmo um Server 64 bits?? não né!


Errado. Ponto flutuante não tem necessariamente a ver com arquitetura. Alguns processadores mais simples só trabalham com inteiros, e toda a representação de FP é feita em software.

Apesar disso, existem representações padronizadas de FP, como a IEEE-754, que podem ser implementadas em hardware ou por software e que funcionam de modo idêntico em qualquer dessas implementações. Para você ter uma ideia, desde o tempo dos XTs de 16bits com MS-DOS, desde que equipados com coprocessador matemático 8087, os PCs comuns já podiam se servir do formato IEEE-754, que é o mesmo que se usa, hoje, quase universalmente.

2º voce escolheu um tipo de dado com precisão básica( FLOAT )
tem a precisao de: -3.4E- 38 a 3.4E+38

se voce quer mais precisa use o Double: - 1.7 E-308 a 1.7 E+308

com o dobro de Bytes para o armazenamento creio que de pra suprir os seus cálculos.

fonte: http://pt.kioskea.net/faq/10173-linguagem-c-tipos-de-dados
https://en.wikipedia.org/wiki/C_data_types
http://tsiad.ifsul.edu.br/moodle/conteudo/modulo1/lop/lop_ug/at2/02.pdf


Usar mais bits de precisão não necessariamente elimina erros de arredondamento: geralmente só os empurra algumas casas mais para a direita.

se mesmo assim não for suficiente.. não use o long double do c ele so aceita valores positivos.


Viajou!!

se tudo que eu disse não for o suficiente..
voce vai ter que usar a linguagem de programação que os físicos usam FORTRAN ( 95 )


Não muda nem uma letra das considerações acima.

Você deveria saber que Informática não é mágica. Far-lhe-ia muito bem estudar uma disciplina chamada "Cálculo Numérico".

veja os tipos de dados:
http://docs.oracle.com/cd/E19957-01/805-4939/6j4m0vn6o/index.html

veja a comparação o

double do C tem 4 Bytes de precisão
o Double do Fortran tem de 4 a 32 Bytes de precisão


De onde você tirou isso? Errou tanto nas considerações sobre C (que não estabelece limites exatos para os tipos de dados de FP) quanto na generalização que faz de uma implementação específica de Fortran (no link que você mostrou, 32 bytes só são usados com COMPLEX*32, que é a composição de dois números reais REAL*16 para representar a parte real e a imaginária de um número complexo, e só estão disponíveis numa implementação específica do compilador).

Além do mais, você não leva em conta que o C99 introduziu números complexos com diferentes precisões, análogos aos float, double e long double, e para rivalizar que o que é oferecido pelo Fortran (para mim, é um erro tentar transformar o C num competidor de Fortran, mas é o que o comitê da linguagem tem feito desde o padrão de 1999, e agora, de novo, no de 2011).



bom dia,

Vejo que o Paulo não deu a devida atenção Sam L, mas somente a algumas ambiguidades do que eu disse:

O Paulo comentou:
Errado. Ponto flutuante não tem necessariamente a ver com arquitetura. Alguns processadores mais simples só trabalham com inteiros, e toda a representação de FP é feita em software. Apesar disso, existem representações padronizadas de FP, como a IEEE-754, que podem ser implementadas em hardware ou por software e que funcionam de modo idêntico em qualquer dessas implementações. Para você ter uma ideia, desde o tempo dos XTs de 16bits com MS-DOS, desde que equipados com coprocessador matemático 8087, os PCs comuns já podiam se servir do formato IEEE-754, que é o mesmo que se usa, hoje, quase universalmente.

( realmente ele estaria certo se o mundo fosse perfeito e a computação fosse inventada depois de 1985 a data que criaram essa iso, porém tem vários sistemas que ainda implementam de forma diferente dos de ieee754 pois o que conta é compatibilidade e não uma iso; quer um exemplo disso veja o link que eu mandei da Oraracle.. no cabeçalho tem: Default Alignment SPARC x86 e Alignment in COMMON e os tamanhos de cada Byte muda, isso ta errado Reclama com a SUN foi so um exemplo que o mundo funcionava antes da tua ISO )

O Paulo comentou:
Usar mais bits de precisão não necessariamente elimina erros de arredondamento: geralmente só os empurra algumas casas mais para a direita.
( sim voce ta certo em expressar isso mas ao mesmo tempo não vi voce tentar fazer nada, aqui é não é uma guerra de ego, to tentando ajudar o cara nao discutir contigo sobre arquitetura moderna.. talvez tentando daqui e um pouco de la ele chegue ao que precisa..
um coisa que ve em lógica de programação ou sabe tabela verdade.. nós alteramos parametros para poder ter resultados diferentes... mas fazer o que nao de para acerta de primeiro, mas posso te dizer estou muito mais perto de acertar do que alguém que apenas ACHA QUE SABE E NAO DIZ A NINGUÉM como resolver. )



Comentei
Usar mais bits de precisão não necessariamente elimina erros de arredondamento: geralmente só os empurra algumas casas mais para a direita.
se mesmo assim não for suficiente.. não use o long double do c ele só aceita valores positivos.

O Paulo em seu vocabulário pobre e ofensivo retrucou:
Viajou!!

Apenas errei o termo certo seria
unsigned double, do qual perde totalmente os pontos flutuantes.


O Paulo disse:
Você deveria saber que Informática não é mágica. Far-lhe-ia muito bem estudar uma disciplina chamada "Cálculo Numérico".
sobre o que comentei para mudar de linguagem de programação em que o projeto está.
Você deveria saber que Informática não é mágica. Far-lhe-ia muito bem estudar uma disciplina chamada "Cálculo Numérico".
veja os tipos de dados:
veja a comparação o...
De onde você tirou isso? Errou tanto nas considerações sobre C (que não estabelece limites exatos para os tipos de dados de FP) quanto na generalização que faz de uma implementação específica de Fortran (no link que você mostrou, 32 bytes só são usados com COMPLEX*32, que é a composição de dois números reais REAL*16 para representar a parte real e a imaginária de um número complexo, e só estão disponíveis numa implementação específica do compilador).
Além do mais, você não leva em conta que o C99 introduziu números complexos com diferentes precisões, análogos aos float, double e long double, e para rivalizar que o que é oferecido pelo Fortran (para mim, é um erro tentar transformar o C num competidor de Fortran, mas é o que o comitê da linguagem tem feito desde o padrão de 1999, e agora, de novo, no de 2011).

Paulo sou uma sugestão e sim, levei em consideração o ambiente em que ele esta coisa que voce deve pensar que é algo tipo NASA com máquinas com compiladores de 128 bits.

como expus na questão anterior o meu questionamento, era sobre a precisão apenas comentei sobre o que vejo que é padrão AINDA arquitetura x86,
dentre os padrões C99 e C2011 creio que apenas citar isso seja irrelevante ja que voce não ta propondo nada.. voce ta dizendo, da pra fazer depois disso implementaram tal coisa agora vai..
Proponha exemplos, não fique ai se masturbando com conhecimentos que voce torna tão futeis quanto sua argumentação,

Não vou argumentar contra o seu ultimo paragrafo que parece mais um alocação de ego ja que voce nem responde ao SAM mas somente a minha pessoa.. vejo que curte ser aqueles idiotas que corrigem a todos MAS AINDA ESCREVE MIM NO COMEÇO DE ALGUMA FRASE:

"..Fortran (para mim, é um erro tentar transformar o.."
( ainda tentou disfarçar com a virgula, que esta totalmente no lugar errado. Como voce mesmo gosta de dizer VIAJOU, a não ser que voce fale Tupi Guarani... rsss )

veja o que o Thihup comentou sobre os tipos de retornos..

outra coisa seria interessante saber como as função cos_theta trabalha, mas o jeito é testar... até chegar num ponto comum.


8. Re: Função acos retorno nan [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 01/08/2014 - 13:01h

Caro IZhaq_melo,

Eu alterei algumas coisas na minha postagem anterior, mas você respondeu antes que minhas alterações chegassem ao ar. Eu também não vi sua resposta antes de postar minhas alterações.

Você erra completamente ao dizer que eu faço algum tipo de "guerra de ego". Minha postagem, como todas as minhas postagens nesta comunidade e em outros fóruns de que participo, tão-somente procurava apontar e corrigir imprecisões e erros no seu texto. Não para humilhar alguém, nem tampouco para me gabar, mas para que a ideia ou explicação correta seja dada, e todos, não apenas você, saiam ganhando com isso.

É também absolutamente falso você dizer que eu não ajudei o autor original do tópico. A postagem número 8 [edit: depois de o autor a marcar como "melhor resposta", ela subiu para a posição imediatamente após a pergunta] contém a resposta definitiva para o problema que ele apresentou. Que ele -- ou você -- não a tenha aproveitado é algo que eu possivelmente só devesse ignorar. Se fosse para ignorar qualquer coisa duvidosa ou errônea, no entanto, não haveria motivo sequer para este fórum existir. Como eu, além de não ignorar, ainda insisto em me fazer entender, sou tachado de ególatra e atacado por você.

Espero que você não tenha a ilusão de se achar muito humilde. Se a tem, releia a mensagem que você enviou ao "Sam L." e considere que tipo de impressão passam expressões como "vamos com calma", "não sei se voce sabe" (sic) e "não né!" (sic), e isso só nas duas primeiras linhas.

Não apresento respostas? Faça a prova na sua própria mensagem, e veja se, em lugar de simplesmente apontar seus erros, eu não fui além e indiquei a correção para eles, mesmo na versão anterior à edição que fiz depois.

Você se mostrou muito ofendido quando eu disse que você "viajou" ao escrever algo tão patentemente absurdo que eu julguei que não carecia de explicação (foi o único erro técnico no seu texto para o qual eu não apresentei correção e, por sinal, você agora tentou corrigir com outro absurdo: esse tal "unsigned double"). Admito que não é comum que eu use, por escrito, linguagem informal, mas que esse uso ocasional lhe cause tal escândalo revela mais sobre sua afetação do que qualquer coisa sobre mim. E isso só é reforçado pelo uso que você mesmo faz, contra mim, de um linguajar tão refinado quanto o de dizer que eu sou "um daqueles idiotas" e que fico "me masturbando com conhecimentos" -- além de repetir contra mim o mesmo "viajou" que tanto detestou.

Não vou discutir sobre o meu Português com alguém que usa como principal sinal de pontuação um tal ".." (quando usa) nem sobre minha argumentação com alguém que tenta fazer galhofa sobre NASA e computadores de 128 bits depois de ele mesmo ter indicado 128 bits, por meio de outra linguagem de programação, como solução de um problema em C e numa arquitetura que desconhece.

Quanto a você usar o Thihup como exemplo do que eu supostamente deveria fazer, isso só revela confusão mental. De novo, eu contra-argumento com a mensagem número 8, que é sucinta e resolve cabalmente o problema original. A resposta do Thihup apresenta algo interessante (implementações distintas de uma mesma função matemática para diferentes tipos de dados), mas desvia do problema inicial e ainda tece uma hipótese errônea (falta de parênteses na expressão).






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts