Jump to content

Particularidades do compilador C++


tonux

Recommended Posts

Olá

Ao fazer cálculos mais rigorosos em C++, apercebi-me de certas particularidades:

pow(a,(1/3) não é igual  a pow(a,0.333333). Isto é significativo quando são exigidos cálculos matemáticos nesta área.

Assim, num programa C++ onde figurem raízes cúbicas, por exemplo, é conveniente adicionar a linha na área do cabeçalho   #define ir3  0.333333. Para futuros cálculos utilizaremos pow(a,ir3) .

Em BASIC é indiferente (ver mais abaixo)

 

Nota: isto em relação ao compilador usado por mim( GNU); não utilizei outros (ainda)

#include <iostream>
#include <cmath>

using namespace std;

#define ir3 0.333333

int main()

{ 
	
for (float i=1;i<50;i=i+5)
{
cout<<"valor com 1/3= "<<pow(i,(1/3))<<endl;
cout<<"valor com 0.333333= "<<pow(i,ir3)<<endl;
}

return 0;

}
                                               
 Resultados:
                 valor com 1/3= 1
valor com 0.333333= 1.81712
valor com 1/3= 1
valor com 0.333333= 2.22398
valor com 1/3= 1
valor com 0.333333= 2.51984
valor com 1/3= 1
valor com 0.333333= 2.75892
valor com 1/3= 1
valor com 0.333333= 2.96249
valor com 1/3= 1
valor com 0.333333= 3.14138
valor com 1/3= 1
valor com 0.333333= 3.30192
valor com 1/3= 1
valor com 0.333333= 3.44821
valor com 1/3= 1
valor com 0.333333= 3.58304
                              
dim i as single
const ir3=0.333333

for i=1 to 50 step 5
print
print "com 1/3= ";(i^(1/3))
print
print "com 0.333333= ";(i^ir3)
print
next
end

resultados:

com 1/3=  1

com 0.333333=  1


com 1/3=  1.81712059283214

com 0.333333=  1.817119507551454


com 1/3=  2.223980090569315

com 0.333333=  2.223978312946244


com 1/3=  2.519842099789746

com 0.333333=  2.519839770962227


com 1/3=  2.75892417638112

com 0.333333=  2.758921376513688


com 1/3=  2.96249606840737

com 0.333333=  2.962492851043056


com 1/3=  3.141380652391393

com 0.333333=  3.141377056573129


com 1/3=  3.301927248894626

com 0.333333=  3.301923304724039


com 1/3=  3.44821724038273

com 0.333333=  3.448212971984297


com 1/3=  3.583047871015946

com 0.333333=  3.583043298283729
Link to comment
Share on other sites

isso não é problema do compilador ... é problema do programador ...

- inteiro / inteiro = inteiro

- inteiro / float = float

- float / inteiro = float

- float / float = float

isto é algo que um programador de C se apercebe rapidamente, chamasse elevação do tipo de dados para o tipo de maior representação. isto porque o primeiro exemplo chamasse divisão inteira. isto faz parte da linguagem e não do compilador

isto simplesmente quer dizer que : se queres fazer contas com valores de virgual flutuante, não uses inteiros

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

E a tua questão é?

 

4 horas atrás, tonux disse:

pow(a,(1/3) não é igual  a pow(a,0.333333). Isto é significativo quando são exigidos cálculos matemáticos nesta área.

Claro que não é igual, era suposto ser? 1/3 nem é igual a 0.333333. Como o HappyHippyHippo disse, não é um problema do compilador... nada no teu exemplo é um problema da linguagem, do compilador, ou do que seja, nem dá bem para perceber a ideia de mencionar BASIC... ou a ideia geral do tópico.

Link to comment
Share on other sites

4 horas atrás, Knitter disse:

E a tua questão é?

 

Claro que não é igual, era suposto ser? 1/3 nem é igual a 0.333333. Como o HappyHippyHippo disse, não é um problema do compilador... nada no teu exemplo é um problema da linguagem, do compilador, ou do que seja, nem dá bem para perceber a ideia de mencionar BASIC... ou a ideia geral do tópico.

Acho que era suposto ser. 1:3 (1/3) tem como quociente uma dizima infinita: 0.333333 ...33333.... basta fazer a conta à mão. Também acho que para a mesma operação deveria haver consonância entre as várias linguagens de programação quanto a resultados, embora os estilos de programação sejam diferentes. Ou então pode-se optar(?) por uma divisão inteira e temos o resultado 0. Para a resolução de uma raiz cubica não é muito conveniente. A não ser que se faça o seguinte: na igualdade v=1/3, declarar v como float. Vou experimentar.

Obrigado pelas respostas🙂

Edited by tonux
Link to comment
Share on other sites

#include <iostream>
#include <cmath>

using namespace std;

int main ()
{
   float v;

   cout<<1/3.0<<endl;
   v=1/3.0;
   cout<<v<<endl;
   return 0;
}
  
// resultado para os dois casos: 0.33333

Erro de palmatória. O número 3 (ou no 1 ou os dois) devem ser dados a conhecer como não inteiros, isto é, como 1.0 e/ou 3.0. Senão temos 0 para as duas saídas no programa, se pelo menos um deles não for considerado 'float'.

O compilador tem razão em C++, respeitando as suas regras.

Ok. Obrigado pela ajuda.

Edited by pwseo
Syntax highlight.
Link to comment
Share on other sites

5 hours ago, tonux said:

Acho que era suposto ser. 1:3 (1/3) tem como quociente uma dizima infinita: 0.333333 ...33333.... basta fazer a conta à mão. Também acho que para a mesma operação deveria haver consonância entre as várias linguagens de programação quanto a resultados, embora os estilos de programação sejam diferentes. Ou então pode-se optar(?) por uma divisão inteira e temos o resultado 0. Para a resolução de uma raiz cubica não é muito conveniente. A não ser que se faça o seguinte: na igualdade v=1/3, declarar v como float. Vou experimentar.

Obrigado pelas respostas🙂

 

5 hours ago, tonux said:

Erro de palmatória. O número 3 (ou no 1 ou os dois) devem ser dados a conhecer como não inteiros, isto é, como 1.0 e/ou 3.0. Senão temos 0 para as duas saídas no programa, se pelo menos um deles não for considerado 'float'.

O compilador tem razão em C++, respeitando as suas regras.

Ok. Obrigado pela ajuda.

afinal leste o meu post ? está lá explicado como é que isso funciona !!!

o problema está na tua cabeça, lá porque teres uma ideia fixa de como pensas que a coisas funcionam, não quer dizer que sejam assim.

a meu ver, o problema é mais do BASIC do que do C, no meu prisma é o BASIC que te está a abstrair da conversão, porque a divisão inteira é útil e tem a sua razão. tem haver como as coisas funcionam em termos de memória. a tua afirmação parece indicar que ainda não estás elucidado nessa matéria

se quiseres a divisão seja feita com virgula flutuante, basta fazer uma cast de qualquer parâmetro da operação

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Só para reforçar o que já foi ditto.

1/3 é diferente de 0.33 e diferente de 0.3333 e diferente de 0.333333333333. Logo aqui vai haver uma diferença de resultado que pode ser significativa consoante a magnitude dos dados que estamos a usar!

Ao dizer que 1/3 é igual a 0.33333333333333, por exemplo, estamos a cometer um erro porque na verdade 1/3 = 0.33(3) onde o 3 entre parêntesis é a tal dízima infinita e se é infinita não se pode dizer que é 0.333 ou 0.33333333 ou 0.333333333333....

Mas só estou a reforça ro que já foi ditto!!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

6 horas atrás, HappyHippyHippo disse:

 

afinal leste o meu post ? está lá explicado como é que isso funciona !!!

o problema está na tua cabeça, lá porque teres uma ideia fixa de como pensas que a coisas funcionam, não quer dizer que sejam assim.

a meu ver, o problema é mais do BASIC do que do C, no meu prisma é o BASIC que te está a abstrair da conversão, porque a divisão inteira é útil e tem a sua razão. tem haver como as coisas funcionam em termos de memória. a tua afirmação parece indicar que ainda não estás elucidado nessa matéria

se quiseres a divisão seja feita com virgula flutuante, basta fazer uma cast de qualquer parâmetro da operação

#include <iostream>
using namespace std;

int main()
{
cout<<(1/3);
return 0;
}
  Resultado 0
  -------------------------------------------
  'Programa em BASIC
  print 1/3
  end
  
  Resultado 0.33333

Basta correr estes dois exemplos simples para ser ver a diferença de tratamento que cada compilador dá. Por defeito, o BASIC considera a operação fraccionária; o C++ considera, por princípio uma operação inteira, caso não seja nada especificado.

De facto, acho mais correcta a "posição" do C++: é necessário especificar com rigor o que pretendemos.🙂

Nota: Decidi iniciar-me mais a fundo no C++, agora. Já tinha abordado esta linguagem há uns bons anos atrás (mais de dez), com o C e C++. Contudo, tenho sempre feito alguns programas sempre em BASIC. São (maus) hábitos que se criam.

Link to comment
Share on other sites

3 horas atrás, PsySc0rpi0n disse:

Só para reforçar o que já foi ditto.

1/3 é diferente de 0.33 e diferente de 0.3333 e diferente de 0.333333333333. Logo aqui vai haver uma diferença de resultado que pode ser significativa consoante a magnitude dos dados que estamos a usar!

Ao dizer que 1/3 é igual a 0.33333333333333, por exemplo, estamos a cometer um erro porque na verdade 1/3 = 0.33(3) onde o 3 entre parêntesis é a tal dízima infinita e se é infinita não se pode dizer que é 0.333 ou 0.33333333 ou 0.333333333333....

Mas só estou a reforça ro que já foi ditto!!

Sim, o número de casas decimais/algarismos significativos depende do rigor que pretendemos. Isto é importante, por exemplo, para o cálculo de raízes cúbicas, e não só, num determinado processo e objectivo.

Edited by tonux
Link to comment
Share on other sites

8 minutes ago, tonux said:

Sim, o número de casas decimais/algarismos significativos depende do rigor que pretendemos. Isto é importante, por exemplo, para o cálculo de raízes cúbicas, e não só, num determinado processo e objectivo.

Pronto, para além deste facto e do que o @HappyHippyHippo disse, os resultados estavam a ser diferentes entre Pascal e C/C++... A precedência de operadores faz toda a diferença! E o tipo de dados usados em algumas operações também!

Kurt Cobain - Grunge misses you

Nissan GT-R - beast killer

Link to comment
Share on other sites

42 minutos atrás, PsySc0rpi0n disse:

Pronto, para além deste facto e do que o @HappyHippyHippo disse, os resultados estavam a ser diferentes entre Pascal e C/C++... A precedência de operadores faz toda a diferença! E o tipo de dados usados em algumas operações também!

program est
implicit none

print*, '1/3= ',(1/3)
print*, '1/3.0= ',(1/3.0)

end program


resultado:

1/3=            0
1/3.0=   0.333333343    

Já agora, e por curiosidade, apresento o mesmo cálculo em Fortran 95. Só que está ali um 4 que... não devia lá estar! Aqui, o compilador não andou muito bem. 

Em relação ao C++, o FORTRAN considera as mesmas diferenças de cálculo; os resultados são "idênticos", só que com mais casas decimais para o FORTRAN, fora o tal 4!

Edited by tonux
Link to comment
Share on other sites

15 minutes ago, tonux said:

program est
implicit none

print*, '1/3= ',(1/3)
print*, '1/3.0= ',(1/3.0)

end program


resultado:

1/3=            0
1/3.0=   0.333333343    

Já agora, e por curiosidade, apresento o mesmo cálculo em Fortran 95. Só que está ali um 4 que... não devia lá estar! Aqui, o compilador não andou muito bem. 

Em relação ao C++, o FORTRAN considera as mesmas diferenças de cálculo; os resultados são "idênticos", só que com mais casas decimais para o FORTRAN, fora o tal 4!

isso é problema de representação de um valor de virgula flutuante ao nível do IEEE 754 .  em algum lado a coisa tem que parar e ter um erro ...

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.