Perché non esiste un operatore di alimentazione in Java / C ++?

22

Mentre c'è un tale operatore - ** in Python, mi chiedevo perché Java e C ++ non ne avessero uno anche.

È facile crearne uno per le classi definite in C ++ con overloading dell'operatore (e credo che questo sia possibile anche in Java), ma quando si parla di tipi primitivi come int, double e così via, si avrà per usare la funzione di libreria come Math.power (e di solito devi castare entrambi per raddoppiare).

Quindi, perché non definire un tale operatore per i tipi primitivi?

    
posta RanZilber 03.03.2011 - 09:52
fonte

9 risposte

31

In generale, gli operatori primitivi in C (e per estensione C ++) sono progettati per essere implementabili da hardware semplice in circa una singola istruzione. Qualcosa come l'esponenziazione spesso richiede il supporto del software; quindi non è lì per impostazione predefinita.

Inoltre, è fornito dalla libreria standard della lingua sotto forma di std::pow .

Infine, fare questo per i tipi di dati interi non avrebbe molto senso, perché la maggior parte dei piccoli valori per l'esponenziazione spazza via il range richiesto per int, che è fino a 65.535. Certo, potresti farlo per i doppi e i float ma non per quelli, ma perché rendere la lingua incoerente per una funzione usata raramente?

    
risposta data 03.03.2011 - 09:59
fonte
41

Questa domanda è rispondente per C ++: Stroustrup, "Design ed Evolution of C ++" discute questo nella sezione 11.6.1, pp. 247-250.

Vi erano obiezioni generali sull'aggiunta di un nuovo operatore. Si aggiungerebbe alla tabella di precedenza già complicata. I membri del gruppo di lavoro pensavano che avrebbe dato solo una minima utilità rispetto ad avere una funzione, e volevano essere in grado di sostituire le proprie funzioni a volte.

Non c'era un buon candidato per un operatore. ^ è esclusivo-o, e ^^ ha invitato la confusione a causa della relazione tra & e | e && e || . ! non era adatto poiché ci sarebbe la naturale tendenza a scrivere != per l'esponenziazione di un valore esistente, e questo era già stato preso. Il migliore disponibile potrebbe essere stato *^ , che a quanto pare a nessuno piaceva davvero.

Stroustrup considera nuovamente ** , ma ha già un significato in C: a**p è a volte a cui p punta a, e char ** c; dichiara c come puntatore al puntatore a char . Introducendo ** come token che significa "dichiarazione di un puntatore a puntatore a", "punta su ciò che la prossima cosa punta a" (se si tratta di un puntatore) o "esponenziazione" (se seguito da un numero) ha causato problemi di precedenza. a/b**p dovrebbe analizzare come a/(b**p) se p fosse un numero, ma (a/b) * *p se p fosse un puntatore, quindi questo dovrebbe essere risolto nel parser.

In altre parole, sarebbe stato possibile, ma avrebbe complicato la tabella delle precedenze e il parser, ed entrambi sono già troppo complicati.

Non conosco la storia di Java; tutto quello che potevo fare sarebbe speculare. Per quanto riguarda C, da dove è iniziato, tutti gli operatori C sono facilmente tradotti in codice assembly, in parte per semplificare il compilatore e in parte per evitare di nascondere funzionalità dispendiose in operatori semplici (il fatto che operator+() e altri potrebbero nascondere grande complessità e prestazioni hits è stata una delle prime lamentele sul C ++).

    
risposta data 04.03.2011 - 20:36
fonte
13

I sospetto è perché ogni operatore che introduci aumenta la complessità della lingua. La barriera per l'ingresso è quindi molto alta. Mi trovo a usare esponenziazione molto, molto raramente - e sono più che felice di usare una chiamata al metodo per farlo.

    
risposta data 03.03.2011 - 09:57
fonte
11

I progettisti di linguaggio Java e libreria principale hanno deciso di relegare la maggior parte delle operazioni matematiche a Math classe. Vedi Math.pow () .

Perché? Flessibilità di dare la priorità alle prestazioni rispetto alla precisione bit-per-bit. Andrebbe contro il resto delle specifiche del linguaggio dire che il comportamento degli operatori matematici integrati potrebbe variare da piattaforma a piattaforma, mentre la classe Math afferma specificamente che il comportamento potenzialmente sacrifica la precisione per le prestazioni, quindi fate attenzione all'acquirente:

Unlike some of the numeric methods of class StrictMath, all implementations of the equivalent functions of class Math are not defined to return the bit-for-bit same results. This relaxation permits better-performing implementations where strict reproducibility is not required.

    
risposta data 03.03.2011 - 09:57
fonte
6

L'esponenziazione faceva parte di Fortran sin dall'inizio perché era mirata direttamente alla programmazione scientifica. Ingegneri e fisici lo usano spesso nelle simulazioni, perché le relazioni di legge di potere sono comuni in fisica.

Python ha una strong presenza anche nel calcolo scientifico (ad esempio NumPy e SciPy). Questo, insieme al suo operatore di esponenziazione, suggerisce che fosse anche finalizzato alla programmazione scientifica.

C, Java e C # hanno radici nella programmazione di sistema. Forse è un'influenza che ha impedito l'esponenziazione dal gruppo di operatori supportati.

Solo una teoria.

    
risposta data 03.03.2011 - 11:31
fonte
4

C solo operatori definiti per le operazioni aritmetiche comuni accessibili con l'ALU. Il suo scopo principale era creare un'interfaccia leggibile dall'uomo per il codice Assembly.

C ++ non ha modificato alcun comportamento dell'operatore perché voleva che tutto il codice base scritto in C fosse conforme.

Java ha fatto lo stesso perché non voleva intimidire i programmatori C ++ esistenti.

    
risposta data 03.03.2011 - 09:58
fonte
1

Bene, perché ogni operatore che avrebbe senso per un potere è già in uso. ^ è XOR e ** definisce un puntatore a un puntatore. Quindi, invece, hanno solo una funzione che fa la stessa cosa. (come pow ())

    
risposta data 03.03.2011 - 09:56
fonte
0

Il fatto è che gli operatori aritmetici sono solo scorciatoie di funzioni. (Quasi) Tutto ciò che fai con loro può essere fatto con una funzione. Esempio:

c = a + b;
// equals
c.set(a.add(b));
// or as free functions
set(c, add(a,b));

È solo più prolisso, quindi non vedo nulla di sbagliato nell'usare le funzioni per eseguire "power of".

    
risposta data 03.03.2011 - 11:57
fonte
-1

Addizione / sottrazione / negazione e moltiplicazione / divisione sono operatori matematici di base. Se dovessi fare del potere un operatore, dove ti fermeresti? Operatore root quadrato? Operatore N-root? Operatore logaritmo?

Non posso parlare per i loro creatori, ma posso dire che penso che sarebbe diventato ingombrante e non ortogonale avere tali operatori nella lingua. Il numero di caratteri non alfanumerici / spazi bianchi rimanenti sulla tastiera è piuttosto limitato. Così com'è, è strano che ci sia un operatore modulo in C ++.

    
risposta data 03.03.2011 - 10:01
fonte

Leggi altre domande sui tag