为什么C++没有幂运算符?

31

为什么C++没有幂运算符,而其他许多编程语言都有呢?例如Fortran和Python使用**表示幂运算,在LaTeX中通常使用^


2
在C和C++中,^是异或运算符。 - Graham Borland
3
这并不一定是原因,但在 C 语言中它已经表示异或(XOR)了,如果赋予它其他意义就会破坏与 C 的向后兼容性。 - juanchopanza
2
可能是因为它在许多平台上没有很好的指令映射。 - Alex Chamberlain
2
找到了一个答案 http://programmers.stackexchange.com/questions/54718/why-there-is-no-power-operator-in-java-c (或者至少是其他回答的重复,而不是“该运算符已被使用”) - Trudbert
2
@JamesKanze:现在是2013年,而不是C语言发明的1969年。争论基于C语言家族的语言仍应局限于石器时代可用的内容是过时的思维方式。没有任何有效的理由说明为什么C++不能将指数作为运算符。 - David Hammen
显示剩余6条评论
4个回答

55

C++确实有一个幂运算符——它被写成pow(x, y)

最初,C语言的设计是考虑系统软件方面的,而且没有多少需要使用幂运算符的情况。(但它有按位运算符,如&|,这在许多其他语言中都缺乏。)在C++标准化期间有一些讨论是否添加幂运算符,但最终的共识大致是:

  • 不能使用^,因为它的优先级是错误的(当然,2. ^ 8 == 256.,但2 ^ 8 == 10也不太好)。

  • 不能使用**,因为那会破坏现有程序(可能有类似x**p的东西,其中xintpint*)。

  • 可以使用*^,因为这个序列在C或C++中目前不合法。但这仍然需要引入额外的优先级。

  • C和C++已经有足够多的特殊标记和优先级水平,在与数字社区的讨论后,得出的结论是pow(x, y)没有任何问题。

所以C++将事情留在原地,这似乎并没有引起任何问题。


4
在上下文中,**没有歧义。如果b不是指针,则a ** b在乘法上下文中没有意义,但在指数运算的上下文中是有意义的。我唯一能想到的理由是,C/C++/C#社区认为科学编程不是真正的编程。这是一个重大的冒犯,也是Fortran程序员认为C/C++/C#是较差的科学编程语言的主要原因之一。 - David Hammen
6
@DavidHammen,有一些方法可以消除歧义,类似于在vector<vector<T>>中用于最后一个>>的方法。 但它们涉及到类型相关的分析,其中符号的类型修改了词法分析器的工作方式。 如果**是一个合法的标记,那么最大贪婪规则将将a**b分词为a**b,而不管其实际含义。 - James Kanze
3
委员会实际上与一些数字领域的专家讨论了这个问题,并且他们似乎认为将指数运算符拼写为 pow(x, y) 不是一个问题。*^ 没有被采用的原因之一(也许是主要原因)是因为我们找不到任何在科学界关心它的人。 - James Kanze
5
pow()不是一个运算符。 运算符可以在静态方面进行评估。 所以这段代码无法编译:enum { val = pow(2, 10) };。 - theschmitzer

10
由于两个原因:
  1. 符号 ^ 用于进行按位异或操作

  2. 您可以使用 std::pow 来实现相同的功能。

C++ 的好处是,您可以重载 operator 让它执行任何您希望的功能!
template< typename T >
T operator^( T x, T y ) {
    return std::pow( x, y );
}

然而,需要考虑到当您这样做时,那些了解C++但不了解您(我相信有相当多的人)可能会显著地难以理解您的代码!


5
好的,但为什么? ^ 可以表示乘方,也可以选择其他符号来表示异或 :-) - juanchopanza
6
Fortran使用**表示幂运算。所以你是对的,"^被占用"并不是不提供幂运算作为操作符的真正原因。 - Trudbert
3
你真的会经常使用"power of"这个词组吗?这是否值得将其作为一个独立的运算符来使用? - PlasmaHH
1
@juanchopanza 最初,C语言被设计用于更多或少低级的系统编程中,其中异或比乘幂更频繁。此后,您无法更改运算符而不会面临严重的向后兼容性问题。 - James Kanze
1
@JamesKanze现在这才是一个答案,而且正是我希望引出的答案类型。 - juanchopanza
显示剩余5条评论

1
因为这是一个互斥或位运算符。不过,有一些名为“pow”的函数可以实现您想要的功能。

0

如果你愿意,你可以自己帮助自己

struct DoubleMock
{
    DoubleMock(double v){_v = v;}
    double _v;
};

double operator^(DoubleMock x, DoubleMock y)
{
    return pow(x._v,y._v);
}

double v = DoubleMock(2.0) ^ 2.0;

1
您还必须提供所有操作符集,或者将其隐式转换为double。但是优先级仍然会出错(考虑a + 2^n)。 - Emilio Garavaglia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接