Índice
- Disciplinas Atuais
- Disciplinas Antigas
Uma constante de especial interesse na física é a chamada constante da estrutura fina, α. Esta constante combina a velocidade da luz, c, a carga elétrica do elétron, e, a constante de Planck, h, e a chamada permissividade do vácuo, ɛ0. A relação entre estas quantidades, dada pela fórmula α=e2/2ɛ0hc, determinam as características de nosso universo. Uma pequena variação em seus valores faria com que a fusão nuclear nas estrelas fosse impossível ou que a matéria não pudesse se agregar, tornando nosso universo inviável.
Vamos começar definindo algumas constantes:
#define C_LUZ 299792458 //m/s #define E_ELETRON 1.602176487e-19 // C #define H_PLANCK 6.62606896e-34 // J.s #define P_VACUO 8.854187817e-12 // F/m
Feito isso, podemos calcular alfa universal também como constante:
#define ALFA ((E_ELETRON*E_ELETRON)/(2*P_VACUO*H_PLANCK*C_LUZ))
Também vamos definir algumas constantes auxiliares:
#define MAXLINE 100 #define ERRO 0
Agora, vamos começar a garantir o primeiro item.
Primeiro, vamos ler a linha, com nosso clássico getline(), e converter tudo para maiúsculas, para não ter que esquentar a cabeça com letras minúsculas.
getline(line,MAXLINE); convertemaiusculas(line); //converte todas as letras para maiúsculas
Depois, vamos validar a linha lida e separar os elementos número e letra, que vai dar o que teremos que modificar na chamada da função que vai calcular alfa.
if (valida(line,MAXLINE)) { constante=getnumber(line); switch (letra=getletter(line)){ case 'C': alfa=calcula_alfa(E_ELETRON,P_VACUO,H_PLANCK,constante); break; case 'E': alfa=calcula_alfa(constante,P_VACUO,H_PLANCK,C_LUZ); break; case 'P': alfa=calcula_alfa(E_ELETRON,constante,H_PLANCK,C_LUZ); break; case 'H': alfa=calcula_alfa(E_ELETRON,P_VACUO,constante,C_LUZ); break; default: printf("Letra errada"); break; } printf("O valor de alfa= %12.10e e 1/alfa=%12.10e\n",alfa, 1/alfa);
Vamos agora codificar as funções:
convertemaiusculas() é fácil, mas temos que lembrar de incluir ctype.h:
void convertemaiusculas(char line[]) { int i; for(i=0;line[i]!='\0';i++) line[i]=toupper(line[i]); }
A função de validação vai ser mais chatinha, mas nada impossível, os comentários estão no próprio código:
/** função int valida(char[],int); * retorna ERRO se não for válida a string de entrada. * ou primeira posição após o fim da string válida */ int valida(char line[],int max){ int i=0; //pula espaços em branco. while (line[i]==' ') i++; // testa se começa com dígito ou ponto. if (!isdigit(line[i]) && line[i]!='.') return ERRO; //pula todos os digitos while(isdigit(line[++i])) ; // o caractere seguinte pode ser ponto... // e devemos pular outros digitos até o fim do número. if (line[i]=='.') while (isdigit (line[++i])) ; // ou "E", para o expoente if (line[i]=='E'){ // testa se o expoente tem sinal if (line[++i]=='-' || line[i]=='+') i++; //pula sinal. if (isdigit(line[i])) while (isdigit (line[++i])) ; else // se não for sinal nem dígito, depois de "E", é erro. return ERRO; } // agora tem que vir espaço. if (line[i]!=' ') return ERRO; //agora a letra. switch (line[++i]){ case 'C': case 'P': case 'H': case 'E': return ++i; break; default: return ERRO; } }
O cálculo de alfa também é simples:
/* função calcula_alfa retorna o valor de alfa, dadas as constantes. */ double calcula_alfa(double e_eletron, double p_vacuo, double h_planck, double c_luz) { return (e_eletron*e_eletron)/(2*p_vacuo*h_planck*c_luz); }
Falta a função getnumber(), que nem precisaria estar aqui, pois bastaria usar atof() da stdlib.h, que deve ser incluída no programa, mas fiz isto para manter uma unidade no programa.
/* função getnumber retorna o valor em double de string. poderia ser usado apenas atof no programa principal. */ double getnumber (char line[]){ return atof(line); }
e, finalmente, getletter(), que retorna a letra da constante que devemos converter.
/* retorna o primeiro caractere depois do espaço em branco na string de entrada esta função pressupõe uma string já validada. */ char getletter (char line[]){ int i; char c; for (i=0;isdigit(c=line[i])||c=='.' || c=='E'||c=='-' || c=='+';i++) ; return line[++i]; }
O item 2 é ponto dado. basta criar um arquivo com as constantes e inclui-lo no início de seu programa.
#include "prova2007-2p1.h"
Vamos criar uma função show_dif() que recebe o alfa calculado e compara com a constante universal:
/* imprime os valores absoluto e percentual de diferença */ void show_dif(double alfa_calculado) { double dif=ALFA-alfa_calculado; dif=(dif<0)?-dif:dif; printf("Diferença absoluta= %12.10e\n",dif); printf("Diferença percentual= %.4f%%\n",100*dif/ALFA); }
Este item é mais trabalhoso, mas nada difícil. vamos colocar um switch no programa principal para chamar a função com os valores corretos. Para cada letra, chamamos modifica_alfa() com parâmetros diferentes.
switch (letra){ case 'C': modifica_alfa(letra, E_ELETRON,P_VACUO,H_PLANCK,constante); break; case 'E': modifica_alfa(letra, constante,P_VACUO,H_PLANCK,C_LUZ); break; case 'P': modifica_alfa(letra, E_ELETRON,constante,H_PLANCK,C_LUZ); break; case 'H': modifica_alfa(letra, E_ELETRON,P_VACUO,constante,C_LUZ); break; default: printf("Letra errada"); break; }
A função modifica_alfa() fica assim:
/* função modifica_alfa modifica a constante em 1% até que alfa seja modificado de mis de 4% */ void modifica_alfa( char letra, double e_eletron, double p_vacuo, double h_planck, double c_luz) { double dif, alfa; double umporcento; int sentido; alfa=calcula_alfa(e_eletron,p_vacuo,h_planck,c_luz); sentido=(alfa<ALFA)?-1:1; dif=ALFA-alfa; dif=(dif<0)?-dif:dif; show_dif(alfa); //calcula 1% da variável em questão. switch (letra){ case 'E': umporcento=0.01*e_eletron; break; case 'P': umporcento=0.01*p_vacuo; break; case 'H': umporcento=0.01*h_planck; break; case 'C': umporcento=0.01*c_luz; break; default: printf("Erro\n"); break; } // incrementa ou decrementa de acordo com sentido. umporcento*=sentido; while ( 100*dif/ALFA<4){ switch (letra){ case 'E': alfa=calcula_alfa(e_eletron+=umporcento,p_vacuo,h_planck,c_luz); printf("nova e_eletron=%.10e\n",e_eletron); break; case 'P': alfa=calcula_alfa(e_eletron,p_vacuo+=umporcento,h_planck,c_luz); printf("nova p_vacuo=%.10e\n",p_vacuo); break; case 'H': alfa=calcula_alfa(e_eletron,p_vacuo,h_planck+=umporcento,c_luz); printf("nova h_planck=%.10e\n",h_planck); break; case 'C': alfa=calcula_alfa(e_eletron,p_vacuo,h_planck,c_luz+=umporcento); printf("nova c luz=%.0f\n",c_luz); break; default: printf("Erro\n"); break; } dif=ALFA-alfa; dif=(dif<0)?-dif:dif; show_dif(alfa); } }
O item 5 pede que tratemos até as 4 constantes numa única linha de entrada. A abordagem usada foi converter uma constante de string para double, apagá-la da string e converter a próxima. O processo é repetido até acabar a linha ou uma constante inválida for detectada.
/* calcula alfa com várias constantes modificadas numa única linha */ void calcula_todas(char line[],int max) { int indice,i,j; char letra; double constante, c_luz=C_LUZ, e_eletron=E_ELETRON, h_planck=H_PLANCK, p_vacuo=P_VACUO, alfa; // valida a constante na string, até que não haja mais // constante a ser lida. while (indice=valida(line,max)){ constante=getnumber(line); switch (letra=getletter(line)){ case 'C': c_luz=constante; break; case 'E':e_eletron=constante; break; case 'P': p_vacuo=constante; break; case 'H': h_planck=constante; break; default: printf("Letra errada"); break; } // copia o restante da string para o início, eliminando a que já // foi convertida. for (i=0,j=indice+1;(line[i]=line[j])!='\0';i++,j++) ; } alfa=calcula_alfa(e_eletron, p_vacuo,h_planck,c_luz); printf("O valor de alfa= %12.10e, e 1/alfa=%12.10e\n",alfa, 1/alfa); }
Durante prova, estes itens devem ir se construindo pouco a pouco. Aqui, apresento o resultado final. Primeiro o arquivo prova2007-2p1.h:
/*************************************************************************** * prova2007-2p1.h * * Fri Oct 26 15:00:33 2007 * Constantes da física ****************************************************************************/ #define C_LUZ 299792458 //m/s #define E_ELETRON 1.602176487e-19 // C #define H_PLANCK 6.62606896e-34 // J.s #define P_VACUO 8.854187817e-12 // F/m
Agora o programa completo:
/*************************************************************************** * prova2007-2p1.c * * Fri Oct 26 14:58:46 2007 * Copyright 2007 João Araujo ****************************************************************************/ #include <stdio.h> #include <ctype.h> #include <stdlib.h> #include "prova2007-2p1.h" // calcula alfa como constante. #define ALFA ((E_ELETRON*E_ELETRON)/(2*P_VACUO*H_PLANCK*C_LUZ)) #define MAXLINE 100 #define ERRO 0 int getline(char[],int); void convertemaiusculas(char line[]); int valida(char[],int); double calcula_alfa(double,double,double,double); double getnumber (char[]); char getletter (char[]); void show_dif(double); void modifica_alfa(char, double, double,double,double); void calcula_todas(char[], int); int main(){ char line[MAXLINE]; char numero; char letra; double alfa, constante; printf("O valor de alfa= %12.10e, e 1/alfa=%12.10e\n",ALFA, 1/ALFA); printf("\nQuestão 1: Ler apenas um valor e variar no cálculo de alfa\n"); getline(line,MAXLINE); convertemaiusculas(line); //converte todas as letras para maiúsculas if (valida(line,MAXLINE)) { constante=getnumber(line); switch (letra=getletter(line)){ case 'C': alfa=calcula_alfa(E_ELETRON,P_VACUO,H_PLANCK,constante); break; case 'E': alfa=calcula_alfa(constante,P_VACUO,H_PLANCK,C_LUZ); break; case 'P': alfa=calcula_alfa(E_ELETRON,constante,H_PLANCK,C_LUZ); break; case 'H': alfa=calcula_alfa(E_ELETRON,P_VACUO,constante,C_LUZ); break; default: printf("Letra errada"); break; } printf("O valor de alfa= %12.10e e 1/alfa=%12.10e\n",alfa, 1/alfa); printf("\nQuestão 2: É apenas a inclusão do header de constantes\n"); printf("\nQuestão : Dar diferença em valores absolutos e relativos\n"); show_dif(alfa); printf("\nQuestão 4: Variar constante até que alfa seja mais de 4%% diferente\n"); switch (letra){ case 'C': modifica_alfa(letra, E_ELETRON,P_VACUO,H_PLANCK,constante); break; case 'E': modifica_alfa(letra, constante,P_VACUO,H_PLANCK,C_LUZ); break; case 'P': modifica_alfa(letra, E_ELETRON,constante,H_PLANCK,C_LUZ); break; case 'H': modifica_alfa(letra, E_ELETRON,P_VACUO,constante,C_LUZ); break; default: printf("Letra errada"); break; } printf("\nQuestão 5: Tratar até 4 constantes numa única linha\n"); getline(line,MAXLINE); calcula_todas(line, MAXLINE); } else printf("Erro\n"); } /* getline: get line into s, return length (copiado do livro K&R)*/ int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } void convertemaiusculas(char line[]) { int i; for(i=0;line[i]!='\0';i++) line[i]=toupper(line[i]); } /** função int valida(char[],int); * * retorna ERRO se não for válida a string de entrada. * * ou primeira posição após o fim da string válida * * */ int valida(char line[],int max){ int i=0; //pula espaços em branco. while (line[i]==' ') i++; // testa se começa com dígito ou ponto. if (!isdigit(line[i]) && line[i]!='.') return ERRO; //pula todos os digitos while(isdigit(line[++i])) ; // o caractere seguinte pode ser ponto... // e devemos pular outros digitos até o fim do número. if (line[i]=='.') while (isdigit (line[++i])) ; // ou "E", para o expoente if (line[i]=='E'){ // testa se o expoente tem sinal if (line[++i]=='-' || line[i]=='+') i++; //pula sinal. if (isdigit(line[i])) while (isdigit (line[++i])) ; else // se não for sinal nem dígito, depois de "E", é erro. return ERRO; } // agora tem que vir espaço. if (line[i]!=' ') return ERRO; //agora a letra. switch (line[++i]){ case 'C': case 'P': case 'H': case 'E': return ++i; break; default: return ERRO; } } /* função calcula_alfa retorna o valor de alfa, dadas as constantes. */ double calcula_alfa(double e_eletron, double p_vacuo, double h_planck, double c_luz) { return (e_eletron*e_eletron)/(2*p_vacuo*h_planck*c_luz); } /* função getnumber retorna o valor em double de string. poderia ser usado apenas atof no programa principal. */ double getnumber (char line[]){ return atof(line); } /* retorna o primeiro caractere depois do espaço em branco na string de entrada esta função pressupõe uma string já validada. */ char getletter (char line[]){ int i; char c; for (i=0;isdigit(c=line[i])||c=='.' || c=='E'||c=='-' || c=='+';i++) ; return line[++i]; } /* imprime os valores absoluto e percentual de diferença */ void show_dif(double alfa_calculado) { double dif=ALFA-alfa_calculado; dif=(dif<0)?-dif:dif; printf("Diferença absoluta= %12.10e\n",dif); printf("Diferença percentual= %.4f%%\n",100*dif/ALFA); } /* função modifica_alfa modifica a constante em 1% até que alfa seja modificado de mis de 4% */ void modifica_alfa( char letra, double e_eletron, double p_vacuo, double h_planck, double c_luz) { double dif, alfa; double umporcento; int sentido; alfa=calcula_alfa(e_eletron,p_vacuo,h_planck,c_luz); sentido=(alfa<ALFA)?-1:1; dif=ALFA-alfa; dif=(dif<0)?-dif:dif; show_dif(alfa); //calcula 1% da variável em questão. switch (letra){ case 'E': umporcento=0.01*e_eletron; break; case 'P': umporcento=0.01*p_vacuo; break; case 'H': umporcento=0.01*h_planck; break; case 'C': umporcento=0.01*c_luz; break; default: printf("Erro\n"); break; } // incrementa ou decrementa de acordo com sentido. umporcento*=sentido; while ( 100*dif/ALFA<4){ switch (letra){ case 'E': alfa=calcula_alfa(e_eletron+=umporcento,p_vacuo,h_planck,c_luz); printf("nova e_eletron=%.10e\n",e_eletron); break; case 'P': alfa=calcula_alfa(e_eletron,p_vacuo+=umporcento,h_planck,c_luz); printf("nova p_vacuo=%.10e\n",p_vacuo); break; case 'H': alfa=calcula_alfa(e_eletron,p_vacuo,h_planck+=umporcento,c_luz); printf("nova h_planck=%.10e\n",h_planck); break; case 'C': alfa=calcula_alfa(e_eletron,p_vacuo,h_planck,c_luz+=umporcento); printf("nova c luz=%.0f\n",c_luz); break; default: printf("Erro\n"); break; } dif=ALFA-alfa; dif=(dif<0)?-dif:dif; show_dif(alfa); } } /* calcula alfa com várias constantes modificadas numa única linha */ void calcula_todas(char line[],int max) { int indice,i,j; char letra; double constante, c_luz=C_LUZ, e_eletron=E_ELETRON, h_planck=H_PLANCK, p_vacuo=P_VACUO, alfa; // valida a constante na string, até que não haja mais // constante a ser lida. while (indice=valida(line,max)){ constante=getnumber(line); switch (letra=getletter(line)){ case 'C': c_luz=constante; break; case 'E':e_eletron=constante; break; case 'P': p_vacuo=constante; break; case 'H': h_planck=constante; break; default: printf("Letra errada"); break; } // copia o restante da string para o início, eliminando a que já // foi convertida. for (i=0,j=indice+1;(line[i]=line[j])!='\0';i++,j++) ; } alfa=calcula_alfa(e_eletron, p_vacuo,h_planck,c_luz); printf("O valor de alfa= %12.10e, e 1/alfa=%12.10e\n",alfa, 1/alfa); }
O total de linhas, sem contar as linhas de comentário, foi de 181 linhas.