
		paulo1205
		
		(usa Ubuntu)
		
		Enviado em 23/05/2016 - 17:41h 
		TrueMishima escreveu:
Olá, trata-se de um exercício de recursividade. O problema é quando eu digito tanto um expoente quanto uma base com valores que transbordam o programa sempre acaba dando pau. Até agora eu elaborei isto:
#include <iostream>
#include <stdio.h>
#include <stdlib.h> 
  
Como você parece estar usando C++, não misture cabeçalhos de C com os de C++.  Para recursos de biblioteca herdados do C, use includes na forma <cHEADER> em lugar de <HEADER.h>.
using namespace std;
unsigned int base, expoente, aux, scoAddress; 
  
Você provavelmente não quer usar variáveis globais no seu programa.  Em particular, essa variável 
aux é nociva, e você tem de eliminá-la.
unsigned int exp(unsigned int base, unsigned int expoente, unsigned int &scoAddress){   
EDIT: O enunciado dizia que a função deveria receber um endereço.  Para mim, isso soa como se o terceiro argumento tivesse, obrigatoriamente e explicitamente, de ser um ponteiro.
Você usou referência em vez de ponteiro.  Referências se comportam de modo semelhante ao uso implícito de ponteiros, sem a necessidade de usar os operadores 
& para obter o endereço de dados reais ou 
* para chegar ao dado real a partir do endereço.  Como o enunciado parece apontar no sentido de ser explícito, acho que sua solução pode não ser aceitável.
Além disso, se você usar ponteiros, o uso confuso que você faz mais abaixo (ver explicação também abaixo) provavelmente teria sido evitado.
Além do mais, como você está usando C++ e o valor de retorno indica uma condição de verdadeiro ou falso, possivelmente você poderia usar 
bool como tipo de retorno, em lugar de 
unsigned int;
    if(expoente > 1){
        if(sizeof(base*aux) > sizeof(4))   
Esse uso de 
sizeof está errado.  
sizeof olha apenas para os tipos de dados envolvidos, não para os valores (tanto é que a expressão é avaliada durante a compilação, não durante a execução do programa).  No teste acima, você está vendo se o tamanho de um inteiro sem sinal (que é o tipo da expressão 
base*aux) é maior do que o tamanho de um inteiro com sinal (que é o tipo da expressão 
4); como os dois tamanhos são iguais, seu teste será sempre falso.
O que você quer testar é se 
A*B produz um resultado 
C com 
overflow.  Uma forma de testar isso é dividir 
C por 
A, e ver se o quociente é exatamente igual a 
B e se o resto da divisão é zero.  Para tanto, você pode querer usar a função 
div, declarada em <cstdlib>.
EDIT (para dar cola): Outro jeito é lembrar que o número de dígitos (ou bits) ocupados por um determinado número é proporcional ao logaritmo desses número, e também que o logaritmo de um produto é igual a soma dos logaritmos de cada fator.  Assim, se 
log2(A) (logaritmo na base 2, que, sendo 
A inteiro, efetivamente conta quantos bits são ocupados por 
A) somado a 
log2(B) for menor do que o número de bits do tipo de dados usado para representar o produto, então o resultado certamente será válido.
            return 0;
        else
            exp(base*aux, expoente-1, scoAddress=base*aux); 
  
Aqui a variável global 
aux é usada de maneira nefasta duas vezes.  E, para completar o contrassenso, o valor dela nem é definido dentro da função ou como parte de seus parâmetros.
EDIT: O uso do terceiro argumento também está confuso.  Como a função foi declarada para recebê-lo por referência não-constante, é de se esperar que a função o modifique.  Contudo, você faz uma atribuição de valor que acontece antes da efetiva chamada à função, que vai depois modificar o valor de novo.  Como, porém, a variável passada por referência só é usada nessa linha da função, a atribuição que foi feita antes da chamada acontecer se revela completamente inútil.  E o compilador não teria como prever isso, e consequentemente otimizar o código, porque o fluxo de execução depende (ou deveria depender, se a condição do 
if acima estivesse certa) dos valores da base e do expoente.
Se você tivesse usado ponteiros (ver discussão acima), essa atribuição despropositada possivelmente ficaria mais evidente, pois haveria duas expressões diferentes (ainda que numa só linha e dentro da chamada à função) para fazer o cálculo do valor e guardá-lo na memória indicada pelo ponteiro, e para obter de novo o endereço a ser passado à função.  (Mas não tente nem descobrir como fazer isso, porque a função, como está, está errada de qualquer forma.  É melhor gastar seu tempo corrigindo-a.)
    }
    return 1;
}
int main(){
    cout << "Base:" << endl;
    scanf("%u", &base); 
  
Não é propriamente um erro, mas por que essa mistura de I/O ao estilo de C com a ao estilo C++?  A não ser que haja alguma boa razão para fazê-lo, procure usar consistentemente apenas um estilo.
Eis aí: um elemento estranho à função, mas que é fundamental para que a função funcione.
Não faça isso.  Se a função precisar de auxiliares, deixe-os internos à função.  No seu caso, nem mesmo precisa, pois seu auxiliar é a própria base, que já é argumento da função, e que não vai ser alterada no interior da função (depois que ela for devidamente corrigida).
    cout << "Expoente:" << endl;
    scanf("%u", &expoente);
    scoAddress=exp(base, expoente, scoAddress); 
  
Notou que há na expressão acima dois lugares em que o valor de 
scoAddress é modificado?  Para você saber, primeiro ele é alterado dentro da função, durante sua execução, e, depois que ela retorna, o que quer que tenha sido gravado será sobrescrito com o valor retornado pela função.
Só que o valor de retorno, como você deve se lembrar, não é o da exponenciação, mas sim um sinalizador de se houve overflow ou não.  Então, no fim das contas, você calcula (ou tenta calcular) uma potência, e o resultado não fica guardado em lugar nenhum!
    printf("%u", scoAddress);
    cout << endl << endl;
    system("pause");   
Toda vez que alguém usa 
system("pause"), tal pessoa deveria ser obrigada a pagar uma multa. ;)