Esiste un operatore esponente in C #?


194

Ad esempio, esiste un operatore per gestirlo?

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Number1 (operator) Number2;

In passato l' ^operatore è stato un operatore esponenziale in altre lingue, ma in C # è un operatore bit-saggio.

Devo scrivere un ciclo o includere un altro spazio dei nomi per gestire le operazioni esponenziali? In tal caso, come gestisco le operazioni esponenziali utilizzando numeri non interi?


7
Non è in C #, ma molte lingue usano **come operatore di esponenziazione infix.
Mark Rushakoff,

venuto qui perché ero seccato che 10 ^ 7 memorizzati in un lungo / Int64 mi stesse dando "13." Avevo provato anche 1E7, ma questo mi ha dato un errore di tipo. Dato che non vedevo un errore di tipo / errore di sintassi dell'operatore illegale, avevo supposto che il mio 10 ^ 7 funzionasse ...
mpag

1
@mpag ^ è l'esclusivo o l'operatore, quindi 10 ^ 7 = 1010b XOR 0111b = 1101b = 13.
Ian Brockbank

Risposte:


228

Il linguaggio C # non ha un operatore di potenza . Tuttavia, .NET Framework offre il metodo Math.Pow :

Restituisce un numero specificato elevato alla potenza specificata.

Quindi il tuo esempio sarebbe simile al seguente:

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Math.Pow(Number1, Number2);

1
Tenete a mente la penalizzazione delle prestazioni se si utilizza Math.pow per la squadratura: stackoverflow.com/questions/936541/...
Justas

4
@Justas Ho appena testato che su .NET Core 2.1 e Math.Pow è ora più veloce dell'implementazione alternativa suggerita.
bytedev,

50

Mi sono imbattuto in questo post cercando di usare la notazione scientifica nel mio codice, ho usato

4.95*Math.Pow(10,-10);

Ma dopo ho scoperto che puoi fare

4.95E-10;

Ho pensato di aggiungere questo per chiunque si trovasse in una situazione simile in cui mi trovavo.


34

C'è un post sul blog su MSDN sul perché un operatore esponente NON esiste dal team C #.

Sarebbe possibile aggiungere un operatore alla lingua, ma eseguire questa operazione è una cosa abbastanza rara da fare nella maggior parte dei programmi e non sembra giustificato aggiungere un operatore quando chiamare Math.Pow () è semplice.


Hai chiesto:

Devo scrivere un ciclo o includere un altro spazio dei nomi per gestire le operazioni esponenziali? In tal caso, come gestisco le operazioni esponenziali utilizzando numeri non interi?

Math.Pow supporta doppi parametri, quindi non è necessario che tu scriva il tuo.


24
Capisco l'argomento, ma un motivo valido sarebbe che Math.Pow () non può essere usato per impostare valori const, il che rende gli esponenti inutilizzabili per tutte le costanti.
jsmars,

1
Un operatore di potenza sarebbe conveniente per il sovraccarico dell'operatore, per me Math.Pow () non giustifica il fatto di non creare un operatore esponente in quanto Math.Pow () non è un operatore e quindi non ha gli stessi usi di un operatore ._ .
Alexandre Daubricourt,

8

La mancanza di un operatore esponenziale per C # è stata una grande seccatura per noi quando cercavamo una nuova lingua per convertire il nostro software di calcolo dal buon vecchio vb6.

Sono contento che siamo andati con C # ma mi dà ancora fastidio ogni volta che scrivo un'equazione complessa che include esponenti. Il metodo Math.Pow () rende le equazioni abbastanza difficili da leggere IMO.

La nostra soluzione era quella di creare una classe DoubleX speciale in cui sovrascrivessimo l'operatore ^ (vedi sotto)

Funziona abbastanza bene fintanto che dichiari almeno una delle variabili come DoubleX:

DoubleX a = 2;
DoubleX b = 3;

Console.WriteLine($"a = {a}, b = {b}, a^b = {a ^ b}");

o usa un convertitore esplicito su doppio standard:

double c = 2;
double d = 3;

Console.WriteLine($"c = {c}, d = {d}, c^d = {c ^ (DoubleX)d}");     // Need explicit converter

Un problema con questo metodo è che l'esponente viene calcolato nell'ordine sbagliato rispetto ad altri operatori. Questo può essere evitato mettendo sempre un extra () attorno all'operazione che rende ancora più difficile leggere le equazioni:

DoubleX a = 2;
DoubleX b = 3;

Console.WriteLine($"a = {a}, b = {b}, 3+a^b = {3 + a ^ b}");        // Wrong result
Console.WriteLine($"a = {a}, b = {b}, 3+a^b = {3 + (a ^ b)}");      // Correct result

Spero che questo possa essere d'aiuto ad altri che usano molte equazioni complesse nel loro codice, e forse qualcuno ha anche un'idea di come migliorare questo metodo ?! :-)

Classe DoubleX:

using System;

namespace ExponentialOperator
{
    /// <summary>
    /// Double class that uses ^ as exponential operator
    /// </summary>
    public class DoubleX
    {
        #region ---------------- Fields ----------------

        private readonly double _value;

        #endregion ------------- Fields ----------------

        #region -------------- Properties --------------

        public double Value
        {
            get { return _value; }
        }

        #endregion ----------- Properties --------------

        #region ------------- Constructors -------------

        public DoubleX(double value)
        {
            _value = value;
        }

        public DoubleX(int value)
        {
            _value = Convert.ToDouble(value);
        }

        #endregion ---------- Constructors -------------

        #region --------------- Methods ----------------

        public override string ToString()
        {
            return _value.ToString();
        }

        #endregion ------------ Methods ----------------

        #region -------------- Operators ---------------

        // Change the ^ operator to be used for exponents.

        public static DoubleX operator ^(DoubleX value, DoubleX exponent)
        {
            return Math.Pow(value, exponent);
        }

        public static DoubleX operator ^(DoubleX value, double exponent)
        {
            return Math.Pow(value, exponent);
        }

        public static DoubleX operator ^(double value, DoubleX exponent)
        {
            return Math.Pow(value, exponent);
        }

        public static DoubleX operator ^(DoubleX value, int exponent)
        {
            return Math.Pow(value, exponent);
        }

        #endregion ----------- Operators ---------------

        #region -------------- Converters --------------

        // Allow implicit convertion

        public static implicit operator DoubleX(double value)
        {
            return new DoubleX(value);
        }

        public static implicit operator DoubleX(int value)
        {
            return new DoubleX(value);
        }

        public static implicit operator Double(DoubleX value)
        {
            return value._value;
        }

        #endregion ----------- Converters --------------
    }
}

2

Sono sorpreso che nessuno l'abbia menzionato, ma per il semplice (e probabilmente più incontrato) caso di quadratura, si moltiplica da solo.

float Result, Number1;

Result = Number1 * Number1;

4
la sua non moltiplicazione, il suo potere di.
Henry,

Sì @Henry e come altri hanno già detto, non esiste un operatore. Basta Math.Pow. Stavo solo offrendo una soluzione ovvia al caso più comune.
RubberDuck,

4
Anche molto più veloce diMath.Pow(Number1, 2)
lamont il

2

Dato che nessuno ha ancora scritto una funzione per farlo con due numeri interi, ecco un modo:

private long CalculatePower(int number, int powerOf)
{
    for (int i = powerOf; i > 1; i--)
        number *= number;
    return number;
}
CalculatePower(5, 3); // 125
CalculatePower(8, 4); // 4096
CalculatePower(6, 2); // 36

In alternativa in VB.NET:

Private Function CalculatePower(number As Integer, powerOf As Integer) As Long
    For i As Integer = powerOf To 2 Step -1
        number *= number
    Next
    Return number
End Function
CalculatePower(5, 3) ' 125
CalculatePower(8, 4) ' 4096
CalculatePower(6, 2) ' 36

Qualcuno può spiegare il downvote? Ho testato questo codice e puoi farlo anche su ideone.com/o9mmAo (C #) e ideone.com/vnaczj (VB.NET) - sembra funzionare perfettamente.
Nathangrad,

8
Perché ci sono Math.Pow, quindi il tuo codice è irrilevante
Thaina,

1
Math.Pow () è lento e questo sarà sostanzialmente più veloce finché PowerOf è ragionevolmente piccolo.
Lamont,

3
@Nathangrad Reinventare la ruota (quadrata) è in gran parte considerato un anti-schema. FYI: exceptionnotfound.net/…
bytedev

Inoltre, ci sono modi più veloci per implementare il tuo metodo di alimentazione. Vedi: en.wikipedia.org/wiki/Exponentiation_by_squaring
Jesse Chisholm,

0

Una buona funzione di potere sarebbe

    public long Power(int number, int power) {
        if (number == 0) return 0;
        long t = number;
        int e = power;
        int result = 1;
        for(i=0; i<sizeof(int); i++) {
            if (e & 1 == 1) result *= t;
            e >>= 1;
            if (e==0) break;
            t = t * t;
        }
    }

La funzione `Math.Pow` utilizza la funzione di potenza del processore ed è molto più efficiente.


0

Per quello che vale, mi manca l'operatore ^ quando aumenta una potenza di 2 per definire una costante binaria. Non è possibile utilizzare Math.Pow () lì, ma lo spostamento di un int senza segno di 1 a sinistra in base al valore dell'esponente funziona. Quando avevo bisogno di definire una costante di (2 ^ 24) -1:

public static int Phase_count = 24;
public static uint PatternDecimal_Max = ((uint)1 << Phase_count) - 1;

Ricorda che i tipi devono essere (uint) << (int).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.