Existe-t-il un opérateur exposant en C #?

194

Par exemple, existe-t-il un opérateur pour gérer cela?

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Number1 (operator) Number2;

Dans le passé, l' ^opérateur a servi d'opérateur exponentiel dans d'autres langues, mais en C #, c'est un opérateur bit à bit.

Dois-je écrire une boucle ou inclure un autre espace de noms pour gérer les opérations exponentielles? Si oui, comment gérer les opérations exponentielles à l'aide de non-entiers?

Charlie
la source
7
Ce n'est pas en C #, mais de nombreux langages l'utilisent **comme opérateur d'exponentiation d'infixe.
Mark Rushakoff
est venu ici parce que j'étais fâché que 10 ^ 7 stockés dans un long / Int64 me donnait "13." J'avais également essayé 1E7, mais cela m'a donné une erreur de type. Comme je ne voyais pas d'erreur de type / erreur de syntaxe d'opérateur illégale, j'avais supposé que mon 10 ^ 7 fonctionnait ...
mpag
1
@mpag ^ est l'opérateur exclusif ou, donc 10 ^ 7 = 1010b XOR 0111b = 1101b = 13.
Ian Brockbank

Réponses:

228

Le langage C # n'a pas d'opérateur de puissance . Cependant, le .NET Framework propose la méthode Math.Pow :

Renvoie un nombre spécifié élevé à la puissance spécifiée.

Donc, votre exemple ressemblerait à ceci:

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Math.Pow(Number1, Number2);
dtb
la source
1
Gardez à l'esprit la pénalité de performance si vous utilisez Math.Pow pour l'équerrage: stackoverflow.com/questions/936541/…
Justas
4
@Justas Je viens de tester cela sur .NET Core 2.1 et Math.Pow est maintenant plus rapide que l'implémentation alternative suggérée.
bytedev
50

Je suis tombé sur ce post en cherchant à utiliser la notation scientifique dans mon code, j'ai utilisé

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

Mais après j'ai découvert que tu pouvais faire

4.95E-10;

Je pensais simplement que j'ajouterais cela à toute personne dans une situation similaire à laquelle j'étais.

Général Gray
la source
34

Il existe un article de blog sur MSDN expliquant pourquoi un opérateur exposant N'existe PAS de l'équipe C #.

Il serait possible d'ajouter un opérateur de puissance au langage, mais effectuer cette opération est une chose assez rare à faire dans la plupart des programmes, et il ne semble pas justifié d'ajouter un opérateur lors de l'appel de Math.Pow () est simple.


Tu as demandé:

Dois-je écrire une boucle ou inclure un autre espace de noms pour gérer les opérations exponentielles? Si oui, comment gérer les opérations exponentielles à l'aide de non-entiers?

Math.Pow prend en charge les paramètres doubles, vous n'avez donc pas besoin d'écrire les vôtres.

Brian R. Bondy
la source
24
Je comprends l'argument, mais une raison valable serait que Math.Pow () ne peut pas être utilisé pour définir des valeurs const, ce qui rend les exposants inutilisables pour toutes les constantes.
jsmars
1
Un opérateur de puissance serait pratique pour une surcharge d'opérateur, pour moi Math.Pow () ne justifie pas le fait de ne pas créer d'opérateur exposant car Math.Pow () n'est pas un opérateur et n'a donc pas les mêmes usages qu'un opérateur ._ .
Alexandre Daubricourt
8

L'absence d'un opérateur exponentiel pour C # était une grande gêne pour nous lorsque nous recherchions un nouveau langage pour convertir notre logiciel de calcul à partir du bon vieux vb6.

Je suis content que nous ayons choisi C # mais cela m'ennuie toujours quand j'écris une équation complexe incluant des exposants. La méthode Math.Pow () rend les équations assez difficiles à lire IMO.

Notre solution a été de créer une classe DoubleX spéciale où nous remplaçons l'opérateur ^ (voir ci-dessous)

Cela fonctionne assez bien tant que vous déclarez au moins une des variables comme DoubleX:

DoubleX a = 2;
DoubleX b = 3;

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

ou utilisez un convertisseur explicite sur les doubles standard:

double c = 2;
double d = 3;

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

Un problème avec cette méthode est cependant que l'exposant est calculé dans le mauvais ordre par rapport aux autres opérateurs. Cela peut être évité en mettant toujours un extra () autour de l'opération, ce qui rend encore plus difficile la lecture des équations:

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

J'espère que cela peut être utile à d'autres qui utilisent beaucoup d'équations complexes dans leur code, et peut-être que quelqu'un a même une idée de la façon d'améliorer cette méthode?! :-)

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 --------------
    }
}
Petter
la source
2

Je suis surpris que personne n'ait mentionné cela, mais pour le cas simple (et probablement le plus rencontré) de la quadrature, vous multipliez simplement par lui-même.

float Result, Number1;

Result = Number1 * Number1;
Canard en caoutchouc
la source
4
sa non multiplication, sa puissance de.
Henry
Oui @Henry et comme d'autres l'ont mentionné, un opérateur n'existe pas. Justement Math.Pow. Je proposais simplement une solution évidente au cas le plus courant.
RubberDuck
4
Aussi beaucoup plus rapide queMath.Pow(Number1, 2)
lamont
2

Étant donné que personne n'a encore écrit de fonction pour ce faire avec deux entiers, voici une façon:

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

Alternativement dans 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
Nathangrad
la source
Quelqu'un peut-il expliquer le downvote? J'ai testé ce code et vous pouvez aussi sur ideone.com/o9mmAo (C #) & ideone.com/vnaczj (VB.NET) - il semble fonctionner parfaitement bien.
Nathangrad
8
Parce qu'il y a Math.Pow donc votre code n'est pas pertinent
Thaina
1
Math.Pow () est cependant lent et ce sera beaucoup plus rapide tant que PowerOf est raisonnablement petit.
lamont
3
@Nathangrad Réinventer la roue (carrée) est largement considéré comme un anti-modèle. Pour info: exceptionnotfound.net/…
bytedev
En outre, il existe des moyens plus rapides de mettre en œuvre votre propre méthode d'alimentation. Voir: en.wikipedia.org/wiki/Exponentiation_by_squaring
Jesse Chisholm
0

Une bonne fonction de puissance serait

    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 fonction `Math.Pow` utilise la fonction de puissance du processeur et est très plus efficace.

Warny
la source
0

Pour ce que ça vaut, je manque l'opérateur ^ lors de l'augmentation d'une puissance de 2 pour définir une constante binaire. Impossible d'utiliser Math.Pow () là-bas, mais le décalage d'un entier non signé de 1 vers la gauche par la valeur de l'exposant fonctionne. Quand j'avais besoin de définir une constante de (2 ^ 24) -1:

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

N'oubliez pas que les types doivent être (uint) << (int).

Graham Gunderson
la source