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


23

尽管有这样的运算符- **在Python中,我想知道为什么Java和C ++也没有。

使用运算符重载为用C ++定义的类创建一个对象很容易(而且我相信Java中也可以做到这一点),但是在谈论基本类型(例如int,double等)时,您必须使用库功能类似Math.power(通常必须将两者都强制转换为两倍)。

那么-为什么不为原始类型定义这样的运算符?


8
在C ++中,我们无法创建自己的运算符。您只能重载现有的运算符。

1
@Mahesh,所以我可以创建自己的Number类并重载^运算符以使其成为幂。那真的不算数。

22
@RanZilber:这很重要,因为^运算符的优先级与取幂的优先级不匹配。考虑一下表达式a + b ^ c。在数学中,首先进行(b ^ c)求幂,然后将得到的幂加到a。在C ++中,先执行加法(a + b),然后使用进行^运算符c。因此,即使您确实将^运算符实现为求幂,优先级也会让所有人感到惊讶。
在计算机版上

2
@RamZilber- ^是C ++中的XOR。建议重载运算符应该使用原始数据类型进行操作。

4
@RanZilber:因为使用您提到的任何求幂运算符都不是直观的。我会严重质疑任何使++运算符或!运算符等过载的C ++程序员的能力。等 表示指数。但是您还是无法做到,因为您所讨论的运算符仅接受一个参数。求幂需要两个参数。
在计算机版上

Answers:


32

一般来说,C(以及扩展为C ++)中的原始运算符被设计为可通过简单的硬件在大约一条指令中实现。求幂运算之类的东西通常需要软件支持。因此默认情况下不存在。

此外,它是由语言的标准库以形式提供的std::pow

最后,对整数数据类型执行此操作没有多大意义,因为即使是很小的求幂值也超出了int所需的范围,即65535。当然,您可以对double和float进行此操作,但不能对int进行此操作,但是为什么对于很少使用的功能使语言不一致?


4
虽然我大部分都同意,但是模数运算符不能用于浮点类型与原始数据类型并不一致,但我想它在任何硬件上都不可能是一条指令,这在现在看来已经很普遍了。

@Sion:至少在x86上,模数是一条指令。(DIV除法和模数都可以)但是您已经使我了解了一致性。
Billy ONeal

@Billy ONeal:单个指令中的浮点模数?最近我还没有在大会上乱糟糟地知道自己的情况。如果是这种情况,则应使模运算符适用于浮点类型。

3
@DonalFellows:FORTRAN在拥有类似于bignum支持的任何东西之前就拥有幂运算符。
supercat

1
@DonalFellows:对于整数,幂运算符不如对浮点数有用,但对于小幂(尤其是平方),它肯定可以使用。就我个人而言,我喜欢使运算符不使用字母的方法(就像Pascal div或FORTRAN一样.EQ.);根据语言空白规则,可能有任意数量的运算符,而无需将它们保留为字。
supercat 2014年

41

这个问题对于C ++是可以回答的:Stroustrup,“ C ++的设计和演进”在第11.6.1节,第247-250页中对此进行了讨论。

人们普遍反对添加新的运算符。它将添加到已经过于复杂的优先级表中。该工作组的成员认为,与拥有职能相比,这样做只会带来些许便利,他们希望有时能够替代自己的职能。

没有合适的人选。 ^是异或,并且^^由于&|&&与的关系而引起混乱||!这是不合适的,因为会自然而然地倾向于为!=现有值求幂,而这已经被采纳了。可能是最好的*^,显然没有人真正喜欢。

Stroustrup **再次考虑过,但是在C中已经有了含义: a**p是指向a任何对象的时间p,并char ** c;声明c为的指针char**作为令牌引入的意思是“声明指向指针的指针”,“乘以下一个事物的时间”(如果是指针)或“取幂”(如果后跟数字)会导致优先级问题。 a/b**p将必须像a/(b**p)p是一个数字一样进行解析,但是(a/b) * *p如果p是一个指针,则必须在解析器中进行解析。

换句话说,这是有可能的,但是它将使优先级表和解析器变得复杂,并且两者都已经太复杂了。

我不知道有关Java的故事。我所能做的就是推测。对于C语言,所有C运算符都可以很容易地转换为汇编代码,一方面简化了编译器,另一方面避免了在简单的运算符中隐藏耗时的功能(事实上,operator+()其他运算符可能会隐藏很大的复杂性和性能影响,这是一个事实。关于C ++的早期抱怨)。


2
好答案。我猜Java试图在这方面简化C,所以没有人愿意添加新的运算符。可惜没有人问我,我肯定会喜欢的*^。:D
maaartinus

1
C语言可以进行文本格式化。Fortran的建立是为了进行数学运算,并在20年前进行了复数,幂和矩阵数学运算。
马丁·贝克特

@Martin Beckett:您能找到证据证明C是为文本格式构建的吗?在我看来,这是一种非常笨拙的语言,据我对C语言起源的了解,它最初是为Unix系统编程而设计的。
David Thornley,2012年

@DavidThornley-它被设计为用Unix编写,但是Unix的所有早期用途似乎都是文本格式,并且现在它具有广泛的字符串和I / O库。
马丁·贝克特

6
+1:的现有含义a**p是杀手。(解决该问题的技巧……Brr!)
Donal Fellows

13

怀疑这是因为您引入的每个运算符都会增加语言的复杂性。因此进入的障碍很高。我发现自己很少,很少使用指数运算-而且我很高兴使用方法调用来进行运算。



3
我会用,x**2x**3不是很少使用。编译器了解并针对简单情况进行优化的神奇的pow实现将是不错的选择。
CodesInChaos 2011年

2
@CodeInChaos:但是x * xx * x * x并不是正方形和立方体的不错替代品。
David Thornley

5
@David x*x如果x是一个表达式,您不能简单地写。在最好的情况下,代码变得笨拙,在最坏的情况下甚至变得更慢甚至出错。因此,您需要定义自己的Square和Cube函数。即使这样,代码也比使用**作为幂运算符还要难看。
CodesInChaos 2011年

1
@David我需要在括号中加上括号,但不需要重复多次该表达式并膨胀源代码。这大大降低了可读性。而且只有在编译器可以保证表达式没有副作用的情况下,才有可能使用常见的子表达式消除。至少.net抖动在这方面不太聪明。
CodesInChaos 2011年

11

Java语言和核心库设计人员决定将大多数数学运算委托Math类。参见Math.pow()

为什么?灵活性,可将性能优先于逐位精度。内建数学运算符的行为可能因平台而异,这与语言规范的其余部分背道而驰,而Math类明确指出,该行为可能会牺牲性能的准确性,因此买家请注意:

StrictMath类的某些数字方法不同,Math类的等效函数的所有实现未定义为返回逐位相同的结果。这种放松允许在不需要严格的可重复性的情况下实现性能更好的实现。


6

指数运算从一开始就是Fortran的一部分,因为它直接针对科学编程。工程师和物理学家经常在仿真中使用它,因为幂律关系在物理学中很常见。

Python在科学计算中也有很强的地位(例如NumPy和SciPy)。这与其幂运算符一起,也表明它也针对科学编程。

C,Java和C#扎根于系统编程。也许那是一种影响,使得幂运算不属于受支持的运算符组。

只是一个理论。


4

C仅为ALU可以定义的用于普通算术运算符的运算符。其主要目的是为汇编代码创建人类可读的界面。

C ++不会更改任何操作员的行为,因为它希望所有用C编写的代码库都符合要求。

Java之所以这样做,是因为它不想威胁现有的C ++程序员。


创建C时,在硬件上并不经常缺少乘法和除法,而必须在软件中实现。但是C具有乘法和除法运算符。
siride

@siride:据我所知,PDP-7是第一台运行Unix的计算机,通过其EAE进行了硬件乘法和除法。请参阅:bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf
Tugrul Ates

1

好吧,因为每个对电源有意义的操作员已经在使用中。^是XOR,**是定义指向指针的指针。因此,它们只是具有执行相同功能的功能。(例如pow())


@RTS-语言开发人员是否真的在寻找感觉而不是效率?

一个好的编程语言开发人员会同时考虑这两种情况。关于Java我什么也不能说。但是在c ++中,pow()函数是在编译时计算的。和普通操作员一样高效。

@RTS:该pow()函数在运行时执行其计算,除非您拥有可以为进行连续折叠的编译器pow(),对此我深感怀疑。(不过,有些编译器为您提供了使用处理器内部函数执行计算的选项。)
In silico 2011年

@in silico我并不是说它会计算最终值,而是意味着编译器将优化函数调用,所以您只有原始方程式。

2
@josefx:当然,这是一个很好的理由。单个*是词汇标记,无论它是用于间接还是乘法。一个**有意义的取幂可以是一个或两个词法标记,而且您真的不希望词法分析器必须点击符号表来标记化。
David Thornley

0

事实是,算术运算符只是函数的快捷方式。(几乎)您可以使用功能来完成对它们的所有操作。例:

c = a + b;
// equals
c.set(a.add(b));
// or as free functions
set(c, add(a,b));

它只是比较冗长,所以我看不到使用函数执行“功能强大”的问题。


-1

加法/减法/否定和乘法/除法是基本的数学运算符。如果要使操作员有权力,您将在哪里停下来?平方根运算符?N根运算符?对数运算符?

我不能为他们的创造者说话,但是我可以说我认为在语言中拥有这样的运算符会变得笨拙且不正交。键盘上剩余的非字母数字/空格字符的数量受到限制。实际上,在C ++中有一个模运算符很奇怪。


+1-我不明白为什么拥有mod一个运算符很奇怪。通常是一条指令。这是对整数的原始运算。它在计算机科学中最广泛使用。(实现诸如有界缓冲区之类的东西mod不会发臭)
Billy ONeal

@Billy ONeal:之所以奇怪,是因为它不能与整数类型和浮点类型一起使用。绝对有用,但我不会梦想将其删除。只是古怪而已。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.