【问题标题】:Is there an exponent operator in C#?C#中有指数运算符吗?
【发布时间】:2011-03-03 08:28:08
【问题描述】:

例如,是否存在运营商来处理这个问题?

float Result, Number1, Number2;

Number1 = 2;
Number2 = 2;

Result = Number1 (operator) Number2;

过去,^ 运算符在其他语言中用作指数运算符,但在 C# 中它是按位运算符。

我是否必须编写一个循环或包含另一个命名空间来处理指数运算?如果是这样,我该如何处理使用非整数的指数运算?

【问题讨论】:

  • 它不是 C# 中的,但许多语言使用 ** 作为中缀求幂运算符。
  • 来到这里是因为我很生气存储在 long/Int64 中的 10 ^ 7 给了我“13”。我也尝试过 1E7,但这给了我一个类型错误。因为我没有看到类型错误/非法运算符语法错误,所以我假设我的 10^7 正在工作......
  • @mpag ^ 是异或运算符,所以 10^7 = 1010b XOR 0111b = 1101b = 13。
  • C、C++ 和 C# 没有指数运算符。他们使用 symbol ^ 进行按位异或,因此将 ^ 重载为求幂似乎是不明智的(尽管 BASIC 的悠久传统)。如果有人想添加一个幂运算符,其他选择也有好处。 • FORTRAN 的** 是明智的,因为求幂是“乘法之后的级别”(*)。 • Knuth 的 是合理的,因为求幂是“四分法之前的水平”(↑↑)。 (每种可能性都有优点和缺点(和历史)。)见en.wikipedia.org/wiki/Exponentiation#In_programming_languages

标签: c# operators arithmetic-expressions exponent


【解决方案1】:

它不是运算符,但您可以编写自己的扩展函数。

public static double Pow(this double value, double exponent)
{
    return Math.Pow(value, exponent);
}

这让你可以写

a.Pow(b);

而不是

Math.Pow(a, b);

我认为这使 a 和 b 之间的关系更加清晰 + 你避免一遍又一遍地写“数学”。

【讨论】:

    【解决方案2】:

    由于还没有人编写一个函数来处理两个整数,所以这里有一种方法:

    private static long CalculatePower(int number, int powerOf)
    {
        long result = number;
        for (int i = 2; i <= powerOf; i++)
            result *= number;
        return result;
    }
    

    或者在 VB.NET 中:

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

    【讨论】:

    • 有人可以解释一下否决票吗?我已经测试了这段代码,你也可以在 ideone.com/o9mmAo (C#) 和 ideone.com/vnaczj (VB.NET) 上测试 - 它似乎工作得很好。
    • 因为有 Math.Pow 所以你的代码是无关紧要的
    • Math.Pow() 很慢,只要 PowerOf 相当小,这将大大加快。
    • @Nathangrad 重新发明(方形)轮子在很大程度上被认为是一种反模式。仅供参考:exceptionnotfound.net/…
    • 真的需要VB .NET版本吗??因为 VB .NET 已经有了指数运算符...
    【解决方案3】:

    我很惊讶没有人提到这一点,但对于简单的(可能是最常见的)平方的情况,你只需乘以它自己。

    float someNumber;
    
    float result = someNumber * someNumber;
    

    【讨论】:

    • 它不是乘法,而是它的幂。
    • 是的@Henry,正如其他人所提到的,运营商不存在。只是Math.Pow。我只是为最常见的情况提供了一个明显的解决方案。
    • 也比Math.Pow(Number1, 2)快很多
    【解决方案4】:

    当我们在寻找一种新语言来将我们的计算软件从优秀的 ol' vb6 转换为新语言时,C# 缺少指数运算符是一个很大的烦恼。

    我很高兴我们使用 C#,但每当我编写一个包含指数的复杂方程时,它仍然让我很烦恼。 Math.Pow() 方法使 IMO 很难阅读方程式。

    我们的解决方案是创建一个特殊的 DoubleX 类,我们在其中覆盖 ^-operator(见下文)

    只要您至少将其中一个变量声明为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 --------------
        }
    }
    

    【讨论】:

      【解决方案5】:

      一个好的幂函数应该是

      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函数使用处理器功率函数,效率更高。

      【讨论】:

        【解决方案6】:

        C# 团队有一个blog post on MSDN about why an exponent operator does NOT exists

        可以添加一个电源 语言的运算符,但是 执行此操作是一个相当 在大多数程序中很少做的事情,并且 添加一个似乎没有道理 调用 Math.Pow() 时的运算符是 很简单。


        你问:

        我必须写一个循环还是包含 另一个要处理的命名空间 指数运算?如果是这样,怎么办 我使用处理指数运算 非整数?

        Math.Pow支持双参数,不用你自己写。

        【讨论】:

        • 我理解这个论点,但一个正当的理由是 Math.Pow() 不能用于设置 const 值,这使得指数不能用于所有常量。
        • 幂运算符将便于运算符重载,对我来说 Math.Pow() 并不能证明不创建指数运算符的事实,因为 Math.Pow() 不是运算符,因此没有与运算符相同的用法._.
        • 在 C# 中编写 Unity 游戏时,这是一件相当常见的事情,而当您想要的只是整数的整数幂(如 2^X 或 X^)时,花在双精度求幂上的时间被浪费了2 或 X^3 或类似的东西。我一直都需要它。
        • 我不介意需要更长的时间,但 Math.Pow 使用不精确的双精度数。对转换为双精度的整数值进行简单的加法可以得到类似 n-1.99999999999742 的值,然后将其截断为整数并得到 n-1 而不是 n。
        【解决方案7】:

        C# 语言doesn't have a power operator。但是,.NET Framework 提供了Math.Pow 方法:

        返回指定数字的指定幂。

        所以你的例子应该是这样的:

        float Result, Number1, Number2;
        
        Number1 = 2;
        Number2 = 2;
        
        Result = Math.Pow(Number1, Number2);
        

        【讨论】:

        • 如果使用 Math.Pow 进行平方,请记住性能损失:stackoverflow.com/questions/936541/…
        • @Justas 我刚刚在 .NET Core 2.1 上进行了测试,Math.Pow 现在比建议的替代实现更快。
        • 在尝试调试为什么我的计算不能使用 ^
        • 但是你仍然不能使用它来定义常量,因为它们必须在编译时定义,Math.Pow() 在运行时使用。
        • 正如@z33k 所说,没有常量也意味着没有枚举。这很可悲,因为它使 Flags Enums 更易于阅读。
        【解决方案8】:

        为了定义二进制常量,我确实错过了 ^ 运算符,因为它是 2 的幂。不能在那里使用 Math.Pow() ,但是将无符号整数 1 向左移动指数值是可行的。当我需要定义 (2^24)-1 的常数时:

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

        记住类型必须是 (uint)

        【讨论】:

        • 对于小数字(如标志枚举),您可以简单地使用 0 -> 0 | 1 -> 1 1 1
        【解决方案9】:

        我偶然发现这篇文章希望在我的代码中使用科学记数法,我使用了

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

        但后来我发现你可以做到

        4.95E-10;
        

        只是想我会为与我遇到类似情况的任何人添加此内容。

        【讨论】:

        • 请记住,E 始终是以 10 为底的指数。我知道如果我们仔细观察,我们会理解这一点,但由于 OP 是关于一般指数的,我认为它值得强调。
        猜你喜欢
        • 2020-11-16
        • 2014-03-31
        • 1970-01-01
        • 2011-03-11
        • 1970-01-01
        • 1970-01-01
        • 2011-10-14
        • 2010-12-03
        相关资源
        最近更新 更多