¿Hay un operador exponente en C #?

194

Por ejemplo, ¿existe un operador para manejar esto?

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Number1 (operator) Number2;

En el pasado, el ^operador ha servido como operador exponencial en otros lenguajes, pero en C # es un operador inteligente.

¿Tengo que escribir un bucle o incluir otro espacio de nombres para manejar operaciones exponenciales? Si es así, ¿cómo manejo las operaciones exponenciales utilizando no enteros?

Charlie
fuente
77
No está en C #, pero muchos lenguajes se usan **como operador de exponenciación infijo.
Mark Rushakoff
Vine aquí porque me molestó que 10 ^ 7 almacenados en un largo / Int64 me estaba dando "13". También probé 1E7, pero eso me dio un error de tipo. Como no estaba viendo un error de tipo de error / ilegal sintaxis del operador, que había asumido mi hijo de 10 ^ 7 estaba trabajando ...
MPAG
1
@mpag ^ es el operador u exclusivo, entonces 10 ^ 7 = 1010b XOR 0111b = 1101b = 13.
Ian Brockbank

Respuestas:

228

El lenguaje C # no tiene un operador de energía . Sin embargo, .NET Framework ofrece el método Math.Pow :

Devuelve un número especificado elevado a la potencia especificada.

Entonces su ejemplo se vería así:

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Math.Pow(Number1, Number2);
dtb
fuente
1
Tenga en cuenta la penalización en el rendimiento si se utiliza Math.pow para elevar al cuadrado: stackoverflow.com/questions/936541/...
Justas
44
@Justas Acabo de probar eso en .NET Core 2.1 y Math.Pow ahora es más rápido que la implementación alternativa sugerida.
bytedev
50

Me topé con esta publicación buscando usar notación científica en mi código, usé

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

Pero luego descubrí que puedes hacer

4.95E-10;

Solo pensé que agregaría esto para cualquier persona en una situación similar en la que estaba.

General gris
fuente
34

Hay una publicación de blog en MSDN sobre por qué NO existe un operador exponente del equipo de C #.

Sería posible agregar un operador avanzado al lenguaje, pero realizar esta operación es algo bastante raro en la mayoría de los programas, y no parece justificado agregar un operador cuando llamar a Math.Pow () es simple.


Tu preguntaste:

¿Tengo que escribir un bucle o incluir otro espacio de nombres para manejar operaciones exponenciales? Si es así, ¿cómo manejo las operaciones exponenciales utilizando no enteros?

Math.Pow admite parámetros dobles, por lo que no es necesario que escriba los suyos.

Brian R. Bondy
fuente
24
Entiendo el argumento, pero una razón válida sería que Math.Pow () no se puede usar para establecer valores constantes, lo que hace que los exponentes sean inutilizables para todas las constantes.
jsmars
1
Un operador de potencia sería conveniente para la sobrecarga del operador, para mí Math.Pow () no justifica el hecho de no crear un operador exponente como Math.Pow () no es un operador y, por lo tanto, no tiene los mismos usos que un operador ._ .
Alexandre Daubricourt
8

La falta de un operador exponencial para C # fue una gran molestia para nosotros cuando buscábamos un nuevo lenguaje para convertir nuestro software de cálculo del buen vb6.

Me alegro de haber elegido C #, pero todavía me molesta cuando escribo una ecuación compleja que incluye exponentes. El método Math.Pow () hace que las ecuaciones sean bastante difíciles de leer en la OMI.

Nuestra solución fue crear una clase especial de DoubleX donde anulamos el operador ^ (ver más abajo)

Esto funciona bastante bien siempre que declare al menos una de las variables como DoubleX:

DoubleX a = 2;
DoubleX b = 3;

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

o use un convertidor explícito en dobles estándar:

double c = 2;
double d = 3;

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

Sin embargo, un problema con este método es que el exponente se calcula en el orden incorrecto en comparación con otros operadores. Esto se puede evitar poniendo siempre un extra () alrededor de la operación, lo que nuevamente hace que sea un poco más difícil leer las ecuaciones:

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

¡Espero que esto pueda ser de ayuda para otros que usan muchas ecuaciones complejas en su código, y tal vez alguien tenga una idea de cómo mejorar este método ?! :-)

Clase 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
fuente
2

Me sorprende que nadie haya mencionado esto, pero para el caso simple (y probablemente más frecuente) de cuadratura, simplemente se multiplica por sí mismo.

float Result, Number1;

Result = Number1 * Number1;
RubberDuck
fuente
44
no es multiplicación, su poder de.
Henry
Sí @Henry y como otros han mencionado, no existe un operador. Justo Math.Pow. Solo estaba ofreciendo una solución obvia para el caso más común.
RubberDuck
44
También mucho más rápido queMath.Pow(Number1, 2)
lamont
2

Como nadie ha escrito aún una función para hacer esto con dos enteros, aquí hay una manera:

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

Alternativamente en 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
fuente
¿Alguien puede explicar el voto negativo? He probado este código y usted también puede hacerlo en ideone.com/o9mmAo (C #) e ideone.com/vnaczj (VB.NET): parece funcionar perfectamente bien.
Nathangrad
8
Porque hay Math.Pow, por lo que su código es irrelevante
Thaina
1
Sin embargo, Math.Pow () es lento y esto será sustancialmente más rápido siempre que PowerOf sea razonablemente pequeño.
lamont
3
@Nathangrad Reinventar la rueda (cuadrada) se considera en gran medida un antipatrón. FYI: exceptionnotfound.net/…
bytedev
Además, hay formas más rápidas de implementar su propio método de potencia. Ver: en.wikipedia.org/wiki/Exponentiation_by_squaring
Jesse Chisholm
0

Una buena función de potencia sería

    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 función `Math.Pow` usa la función de potencia del procesador y es altamente más eficiente.

Warny
fuente
0

Por lo que vale, extraño el operador ^ al aumentar una potencia de 2 para definir una constante binaria. No se puede usar Math.Pow () allí, pero el desplazamiento de un int sin signo de 1 a la izquierda por el valor del exponente funciona. Cuando necesitaba definir una constante de (2 ^ 24) -1:

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

Recuerde que los tipos deben ser (uint) << (int).

Graham Gunderson
fuente