2015-06-19 10 views
6

Ho bisogno di scrivere un metodo in java per restituire la potenza del solo numero intero e voglio che questo metodo restituisca -1 o faccia eccezione se il numero supera il numero intero. MAX_VALUE:Ho bisogno di scrivere un metodo che restituisca la potenza solo dei numeri interi

ho provato il primo e click:

public static int GetPower(int base, int power) 
{ 
    int result = 1; 

    for(int i = 1; i<=power; i++) 
    { 
     result *= base; 
     if (result < 0) { 
      break; // not very acurate 
     } 
    } 
    if (result < 0) { 
     return -1; 
    } 
    return result; 
} 

è il precedente metodo preciso, come dopo il debug ho trovato che quando il risultato supera l'Integer.MAX_VALUE andrà al numero negativo, o ci è un altro modo di gestire questo?

+1

è possibile convertire la base e l'alimentazione in 'BigDecimals', quindi confrontare i risultati con' Integer.MAX_VALUE' – user902383

+1

@ user902383 mentre si ha assolutamente ragione per il caso 'int' (dove è possibile utilizzare' bigint' per convalidare) sarebbe interessante come puoi gestirlo per 'bigints' allora? – dognose

+0

In alternativa è possibile dividere Integer.MAX_VALUE per base e quando il risultato sarà superiore a tale valore, errore di ritorno – user902383

risposta

4

Il metodo funzionerà se la base può essere solo un numero intero positivo. L'underflow potrebbe accadere che la tua base sia un numero intero negativo e il tuo potere è un numero dispari.

Un modo semplice ma non ottimale per gestire questa situazione consiste nell'utilizzare un tipo di dati lungo per memorizzare l'output e confrontare l'output per verificare se è compreso tra Integer.MAX_VALUE e Integer.MIN_VALUE.

public static int GetPower(int base, int power){ 
long result = 1; 

for(int i = 1; i <= power; i++) 
{ 
    result *= base; 
    if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE) { 
     return -1; 
    } 
} 
return result; 
} 
+2

Ha. Se si desidera consentire alla base di essere negativa, questa risposta è migliore della mia. – Nitram

0

Il controllo è sbagliato. Prova il tuo metodo con 1 < 32 e 2 come parametri.

Il controllo corretto sarà simile a questo result==result*base/base se è vero di quanto sia possibile moltiplicare result e base senza eccedere.

2

L'effetto che hai notato è un overflow numerico. Se ne aggiungi uno a Integer.MAX_VALUE otterrai Integer.MIN_VALUE come risultato.

Ora quello che ti serve è più spazio per memorizzare il tuo valore. Poiché vuoi lavorare all'interno dello spazio intero a 32 bit, hai bisogno della prossima cosa più grande. E questo sarebbe un valore Long a 64 bit. Questo è in ogni caso più veloce rispetto a qualsiasi altro BigDecimals utilizzo.

Devi solo controllare all'interno di ogni passo del ciclo se il tuo valore ha superato Integer.MAX_VALUE e cancellarlo, se ciò accade.

Quindi il codice risultante sarebbe qualcosa di simile:

public static int GetPower(int base, int power) 
{ 
    long result = 1; 

    for(int i = 1; i <= power; i++) 
    { 
     result *= base; 
     if (result > Integer.MAX_VALUE) { 
      return -1; 
     } 
    } 
    return result; 
} 

Inoltre vi consiglio di convalidare l'input della funzione di assicurare che la base non è negativo.

3

Nitram e PythaLye delle risposte funzionano, ma non mi piace l'idea di utilizzare un altro tipo di dati per controllare i confini. Invece, io suggerirei di usare questo semplice controllo:

// This basically means result * base > boundary 
if ((base > 0 && result > (Integer.MAX_VALUE/base)) 
    || (base < 0 && result < (Integer.MIN_VALUE/-base)) // Negative base case 
{ 
    return -1; 
} 

Quindi il codice sarebbe:

public static int GetPower(int base, int power) 
{ 
    int result = 1; 

    for(int i = 1; i<=power; i++) 
    { 
     if ((base > 0 && result > (Integer.MAX_VALUE/base)) 
      || (base < 0 && result < (Integer.MIN_VALUE/-base)) { 
      return -1; 
     } 

     result *= base; 
    } 

    return result; 
} 
+1

Che in realtà non funziona. Ad esempio se 'base' è negativo il' (Integer.MIN_VALUE/base) 'avrà un grande valore positivo. I valori legali di 'result' saranno sempre inferiori a questo valore. Vuoi che il tuo caso negativo legga '(Integer.MIN_VALUE/-base)' – Nitram

+1

Buona cattura @Nitram, corretta ora –

2

Come avete semplice implementazione del metodo pow, che non accetta numeri o valori negativi, il mio suggerimento sarà quello di creare il massimo valore consentito e controllare che il risultato sia inferiore a quello.

public static int getPower(int base, int power) 
    { 
     int result = 1; 
     int maxAllowed = Integer.MAX_VALUE/base; 

     for(int i = 1; i<=power; i++) 
     { 
      result *= base; 
      if (i!=power && result>=maxAllowed){ 
       return -1; 
      } 

     } 

     return result; 
    } 

Ma, in generale, mi consiglia di non reinventare ruote, e andare con Math.pow metodo

0

C'è già una funzione di potenza perfettamente valida in java.lang.Math.Consiglio vivamente di farne uso per coprire i casi limite.

public class GetPower { 

    public static int getPower(int base, int power) { 
     double result = Math.pow(base, power); 
     // check result in range 
     if (result > Integer.MAX_VALUE) 
      return -1; 
     if (result < Integer.MIN_VALUE) 
      return -1; 
     return (int) result; 
    } 

    public static void main(String[] args) { 
     for (int base=0; base<=10; ++base) { 
      for (int power=0; power<=10; ++power) { 
       int result = getPower(base, power); 
       System.out.println("getPower(" + base + ", " + power + ") = " + result); 
      } 
     } 
    } 

} 

Non è necessario reinventare la ruota. Non c'è bisogno di preoccuparsi delle inesattezze in virgola mobile - tutti i valori int sono perfettamente rappresentabili come double.

2

Come già accennato, l'utilizzo di un tipo di dati "più grande" consente la convalida e il calcolo semplice - ma cosa succede se non c'è un tipo di dati più grande??

È possibile matematicamente prova, se si tradurrebbe in un overflow:

Se si caluclating base^power, questo significa base^power = result - significa anche power-th square of result = base - il massimo risultato consentito è Integer.MAX_VALUE - altrimenti si ha un overflow.

La power-th root di qualsiasi numero maggiore di zero sarà SEMPRE essere all'interno della gamma ]0,number] - nessuna possibilità di aritmetica overflow.

Quindi - confrontiamo la base che si sta utilizzando con il power-th root di Integer.MAX_VALUE - è baseGRANDE? Poi si verifica un trabocco - altrimenti sarebbe attaccare soffietto (o essere uguale) al risultato di Integer.MAX_VALUE

private static double powSafe(double base, int pow){ 
    //this is the p-th root of the maximum integer allowed 
    double root = Math.pow(Integer.MAX_VALUE, 1.0/pow); 

    if (root < base){ 
     throw new ArithmeticException("The calculation of " + base + "^" + pow + " would overflow."); 
    }else{ 
     return Math.pow(base, pow); 
    } 
} 

public static void main(String[] argv) 
{ 
    double rootOfMaxInt = Math.pow(Integer.MAX_VALUE, 1.0/2); 
    try{ 
     //that should be INTEGER.MAX_VALUE, so valid. 
     double d1 = powSafe(rootOfMaxInt, 2); 
     System.out.println(rootOfMaxInt + "^2 = " + d1); 
    }catch (ArithmeticException e){ 
     System.out.println(e.getMessage()); 
    } 

    try{ 
     //this should overflow cause "+1" 
     double d2 = powSafe(rootOfMaxInt +1, 2); 
     System.out.println("("rootOfMaxInt + "+ 1)^2 = " + d1); 
    }catch (ArithmeticException e){ 
     System.out.println(e.getMessage()); 
    } 

    double the67thRootOfMaxInt = Math.pow(Integer.MAX_VALUE, 1.0/67); 
    try{ 
     //and so, it continues 
     double d3 = powSafe(the67thRootOfMaxInt, 67); 
     System.out.println(the67thRootOfMaxInt + "^67 = " + d3); 

     double d4 = powSafe(the67thRootOfMaxInt +1, 67); 
     System.out.println("(" + the67thRootOfMaxInt + " + 1)^67 = " + d3); 

    }catch (ArithmeticException e){ 
     System.out.println(e.getMessage()); 
    } 
} 

porta a

46340.950001051984^2 = 2.147483647E9 
The calculation of 46341.950001051984^2 would overflow. 
1.3781057199632372^67 = 2.1474836470000062E9 
The calculation of 2.378105719963237^67 would overflow. 

nota, che ci sono imprecisioni che appaiono causa doppio non ha alcun infinita precisione, che già tronca l'espressione 2nd square of Integer.Max_Value, causa Integer.Max_value è dispari.

Problemi correlati