2012-01-15 4 views
8

Attualmente sto scrivendo un metodo compareTo per le funzioni quadratiche nella forma: ax^2 + bx + c.Come si implementano metodi di confronto in modo pulito?

a, b, c sono coefficienti interi che vengono passati alla classe tramite il costruttore.

Nel metodo compareTo, dovrei prima confrontare gli a-coefficienti tra due funzioni, ma se sono uguali, confronto i coefficienti b. Se le b sono uguali, confronto le c.

Il metodo che mi è venuta per questo ha finito per essere abbastanza brutto:

public int compareTo(QuadraticFunction other) 
{ 
    if (a > other.a) 
     return 1; 
    else if (a < other.a) 
     return -1; 
    else if (b > other.b) 
     return 1; 
    else if (b < other.b) 
     return -1; 
    else if (c > other.c) 
     return 1; 
    else if (c < other.c) 
     return -1; 
    else 
     return 0; 
} 

Quindi mi chiedevo, se si dispone di questi sistemi "a più livelli" di confronto (come confrontare una della prima di B di prima c di), qual è il modo migliore per implementarli? Non riesco a immaginare di scrivere un metodo come il mio se devi passare attraverso 10+ variabili.

risposta

6

Per un numero arbitrario di coefficienti (tutti dello stesso tipo), è necessario memorizzarli in un List (o qualcosa di simile) anziché in variabili membro nominate singolarmente. Ciò ti consente di convertire il tuo codice di esempio in una iterazione.

+0

Grazie per l'aiuto! – CowZow

+1

Funziona solo se tutte le variabili hanno lo stesso tipo. –

+0

@LouisWasserman: È corretto. Ma penso che sia abbastanza sicuro assumere che si rappresenterebbero coefficienti polinomiali con tipi omogenei. –

0

È possibile utilizzare un linguaggio simile al seguente che interrompe il confronto in sezioni chiare per campo, richiede solo un test per campo e utilizza il metodo signum per produrre i valori restituiti.

nota, la sottrazione di seguito opere per int, short, char o byte campi. Per i campi long, float e double è necessario utilizzare i controlli separati per < e == per evitare l'overflow/underflow e la perdita di precisione a causa dell'arrotondamento. Prestare attenzione a NaN anche quando si confrontano i valori in virgola mobile. Per i campi Comparable, è possibile impostare delta sul risultato di compareTo dopo aver utilizzato condizioni separate per gestire null.

long delta = ((long) a.field1) - b.field1; 
if (delta != 0) { return Long.signum(delta); } 

delta = ((long) a.field2) - b.field2; 
if (delta != 0) { return Long.signum(delta); } 

... 

return 0; 
+0

Funzionerà correttamente solo se 'a.field1' e co sono al massimo interi. – Voo

+0

@Voo, vero. L'OP dice "a, b, c sono coefficienti interi". –

+0

Ah mentre leggevo la domanda ho interpretato "coefficiente intero" nel senso matematico della parola, ma sì è probabilmente più probabile che intendesse realmente int integer. Tuttavia penso che un grande avvertimento importante sia importante quando si usa questo idioma: è stato usato per decenni e quindi sono un po 'cauto con esso. – Voo

1

Per facilitare la lettura, e di utilizzare il built-in confronto metodi per a, b, c, vorrei refactoring a questo:

public int compareTo(QuadraticFunction other) { 
    if (a.equals(other.a)) { 
     if (b.equals(other.b)) 
      return c.compareTo(other.c); 
     return b.comapreTo(other.b); 
    } 
    return a.compareTo(other.a); 
} 

Questo codice presuppone che i campi sono Number. Se sono primitivi, convertili in tipo incapsulato o cambia a.equals(b) to a == b and change a.compareTo (b) to a - b`.

Si noti inoltre che quando viene restituito un numero if, non è mai necessario un else - è ridondante, quindi rimuoverlo.

+0

Si potrebbe sostenere che il mantenimento del 'else' facilita il refactoring. Nel caso dell'OP, (s) potrebbe decidere in seguito di cambiare il codice in 'if (cond1) {retval = 1; } else if (cond2) {retval = -1; } else ... return retval; '. –

2

Il Guava Libraries fornisce uno strumento estremamente piacevole per fare ciò chiamato ComparisonChain.

Il codice dovrebbe essere simile a questa:

import com.google.common.base.ComparisonChain; 
... 
public int compareTo(QuadraticFunction other) { 
    return ComparisonChain.start() 
    .compare(a, other.a) 
    .compare(b, other.b) 
    .compare(c, other.c) 
    .result(); 
} 
+0

La nuova API Java8 'Comparator' garantisce la propria risposta, o dovremmo forse fonderla lì? –