Чи є в C # оператор-експонент?


194

Наприклад, чи існує оператор для цього?

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Number1 (operator) Number2;

У минулому ^оператор виконував функції експоненціального оператора іншими мовами, але в C # це трохи розумний оператор.

Чи потрібно писати цикл чи включати іншу область імен для обробки експоненціальних операцій? Якщо так, то як мені обробляти експоненціальні операції, використовуючи не цілі числа?


7
Це не в C #, але багато мов використовують **як оператор експоненції інфіксації.
Марк Рушакофф

прийшов сюди, тому що мені було пом'якшено, що 10 ^ 7, що зберігається довго / Int64 давав мені "13." Я також спробував 1E7, але це дало мені помилку типу. Оскільки я не бачив помилки типу / помилки синтаксису оператора, я припустив, що моє 10 ^ 7 працює ...
mpag

1
@mpag ^ - ексклюзивний або оператор, тому 10 ^ 7 = 1010b XOR 0111b = 1101b = 13.
Ян Брокбанк

Відповіді:


228

У мові C # немає оператора живлення . Однак .NET Framework пропонує метод Math.Pow :

Повертає вказане число, підняте до вказаної потужності.

Так ваш приклад виглядав би так:

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Math.Pow(Number1, Number2);

1
Майте на увазі втрати продуктивності при використанні Math.pow для зведення в квадрат: stackoverflow.com/questions/936541 / ...
Юстас

4
@Justas Я просто тестую це на .NET Core 2.1 і Math.Pow зараз швидше, ніж пропонована альтернативна реалізація.
bytedev

50

Я наткнувся на цю посаду, прагнучи використовувати наукові позначення у своєму коді, я використав

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

Але згодом я дізнався, що ти можеш зробити

4.95E-10;

Просто подумав, що додам це для тих, хто в подібній ситуації, в якій я був.


34

В MSDN є повідомлення в блозі про те, чому оператор-експонент НЕ існує у команди C #.

Можливо додати енергооператор до мови, але виконання цієї операції є досить рідкісною справою в більшості програм, і не видається виправданим додавати оператора під час виклику Math.Pow () просто.


Ти запитав:

Чи потрібно писати цикл чи включати іншу область імен для обробки експоненціальних операцій? Якщо так, то як мені обробляти експоненціальні операції, використовуючи не цілі числа?

Math.Pow підтримує подвійні параметри, тому немає необхідності писати свої власні.


24
Я розумію аргумент, але вагомою причиною є те, що Math.Pow () не можна використовувати для встановлення const значень, що робить експоненти непридатними для всіх констант.
jsmars

1
Механічний оператор був би зручним для перевантаження оператора, мені Math.Pow () не виправдовує той факт, що не створювати оператора-експонента, оскільки Math.Pow () не є оператором, тому він не має таких самих звичаїв, як оператор ._ .
Олександр Daubricourt

8

Відсутність експоненціального оператора для C # було великим роздратуванням для нас, коли ми шукали нову мову для перетворення нашого програмного забезпечення для обчислення з хорошого ol 'vb6.

Я радий, що ми пішли з C #, але це все ще дратує мене, коли я пишу складне рівняння, включаючи показники. Метод Math.Pow () робить рівняння досить важким для читання IMO.

Нашим рішенням було створити спеціальний клас DoubleX, де ми перекриємо ^ -оператор (див. Нижче)

Це працює досить добре, якщо ви оголосите принаймні одну зі змінних як DoubleX:

DoubleX a = 2;
DoubleX b = 3;

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

або використовувати явний перетворювач для стандартних парних пар:

double c = 2;
double d = 3;

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

Одна з проблем цього методу полягає в тому, що показник обчислюється в неправильному порядку порівняно з іншими операторами. Цього можна уникнути, поставивши додатковий () навколо операції, що знову ускладнює читання рівнянь:

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

Я сподіваюся, що це може допомогти іншим, хто використовує у своєму коді багато складних рівнянь, і, можливо, хтось навіть має уявлення про те, як вдосконалити цей метод ?! :-)

Клас 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

Я здивований, що про це ніхто не згадував, але для простого (і, мабуть, найбільш часто зустрічається) випадку квадратування, ви просто помножите на себе.

float Result, Number1;

Result = Number1 * Number1;

4
його не множення, його сила.
Генрі

Так, @Henry та, як уже згадували інші, оператора не існує. Просто Math.Pow. Я просто пропонував очевидне рішення найпоширенішої справи.
RubberDuck

4
Також набагато швидше, ніжMath.Pow(Number1, 2)
Ламонт,

2

Оскільки ще ніхто не написав функцію робити це з двома цілими числами, ось один спосіб:

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

Як варіант у 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

Може хтось, будь-ласка, пояснить протиріччя? Я перевірив цей код, і ви можете також на ideone.com/o9mmAo (C #) & ideone.com/vnaczj (VB.NET) - він, здається, працює чудово.
Натанград

8
Тому що є Math.Pow, тож ваш код не має значення
Таїна,

1
Math.Pow () повільний, але це буде значно швидше, доки PowerOf буде досить малим.
Ламонт

3
@Nathangrad Повторне винайдення (квадратного) колеса багато в чому вважається анти-схемою.
БЮР

Крім того, трьома швидшими способами реалізувати власний метод живлення. Дивіться: en.wikipedia.org/wiki/Exponentiation_by_squaring
Jesse Chisholm

0

Гарна функція живлення була б

    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;
        }
    }

Функція `Math.Pow` використовує функцію живлення процесора і відрізняється високою ефективністю.


0

Для чого варто пропустити оператор ^ при підвищенні потужності 2 для визначення бінарної константи. Неможливо використовувати Math.Pow () там, але зміщення неподписаного int 1 наліво за значенням показника працює. Коли мені потрібно було визначити константу (2 ^ 24) -1:

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

Пам'ятайте, типи повинні бути (uint) << (int).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.