Embora exista esse operador - **
em Python, eu queria saber por que Java e C ++ não têm um também.
É fácil criar um para as classes que você define em C ++ com sobrecarga de operador (e acredito que isso também é possível em Java), mas ao falar sobre tipos primitivos, como int, double e assim por diante, você terá que usar a biblioteca funcionam como Math.power
(e geralmente têm que converter os dois para dobrar).
Então - por que não definir esse operador para tipos primitivos?
^
operador não corresponde à precedência da exponenciação. Considere a expressãoa + b ^ c
. Em matemática, a exponenciação é realizada primeiro (b ^ c
), depois a potência resultante é adicionada aa
. No C ++, a adição é realizada primeiro (a + b
) e depois o^
operador é executado comc
. Portanto, mesmo se você implementou o^
operador para significar exponenciação, a precedência surpreenderá a todos.^
é um XOR em C ++. É recomendável que o operador sobrecarregado não faça diferente do que um tipo de dados primitivo faz usando-o.++
operador ou o!
operador et. al. significar exponenciação. Mas você não pode, de qualquer maneira, porque os operadores sobre os quais você fala aceitam apenas um argumento; exponenciação requer dois argumentos.Respostas:
De um modo geral, os operadores primitivos em C (e por extensão C ++) são projetados para serem implementáveis por hardware simples em aproximadamente uma única instrução. Algo como exponenciação geralmente requer suporte de software; então não está lá por padrão.
Além disso, é fornecido pela biblioteca padrão do idioma na forma de
std::pow
.Finalmente, fazer isso para tipos de dados inteiros não faria muito sentido, porque a maioria dos pequenos valores de exponenciação amplia o intervalo necessário para int, ou seja, 65.535. Claro, você poderia fazer isso para duplas e flutuantes, mas não para ints, mas por que tornar o idioma inconsistente para um recurso raramente usado?
fonte
DIV
faz divisão e módulo) Você me colocou no ponto de consistência.div
ou FORTRAN com.EQ.
); dependendo das regras de espaço em branco do idioma, pode ser possível ter um número arbitrário de operadores sem exigir que sejam palavras reservadas.Esta pergunta é responsável por C ++: Stroustrup, "Design and Evolution of C ++" discute isso na seção 11.6.1, pp. 247-250.
Havia objeções gerais à adição de um novo operador. Seria adicionado à tabela de precedência já complicada demais. Os membros do grupo de trabalho pensaram que isso daria apenas uma pequena comodidade em relação a uma função, e eles queriam substituir suas próprias funções algumas vezes.
Não havia um bom candidato para um operador.
^
é ou-exclusivo e^^
confusão convidado por causa da relação entre&
e|
e&&
e||
.!
era inadequado, pois haveria a tendência natural de escrever!=
para exponenciação de um valor existente, e isso já foi adotado. O melhor disponível pode ter sido*^
, do qual aparentemente ninguém realmente gostou.Stroustrup considerou
**
novamente, mas já tem um significado em C:a**p
éa
vezes o que quer quep
aponte echar ** c;
declarac
como um ponteiro para o qual apontarchar
. Introduzir**
como um token que significa "declaração de um ponteiro para o ponteiro para", "vezes o que a próxima coisa aponta para" (se for um ponteiro) ou "exponenciação" (se seguido por um número) causou problemas de precedência.a/b**p
teria que analisar comoa/(b**p)
se p fosse um número, mas(a/b) * *p
se p fosse um ponteiro, isso teria que ser resolvido no analisador.Em outras palavras, isso seria possível, mas complicaria a tabela de precedência e o analisador, e ambos já são muito complicados.
Não conheço a história sobre Java; tudo o que eu poderia fazer seria especular. Quanto ao C, onde começou, todos os operadores C são facilmente traduzidos em código de montagem, em parte para simplificar o compilador e, em parte, para evitar ocultar funcionalidades demoradas em operadores simples (o fato de que
operator+()
outros poderiam ocultar uma grande complexidade e ocorrência de desempenho foi um) das primeiras queixas sobre C ++).fonte
*^
. : Da**p
é o assassino. (Os hacks Para contornar esse problema ... Brr!)Eu suspeito que é porque todo operador que você apresenta aumenta a complexidade do idioma. A barreira de entrada é, portanto, muito alta. Eu me vejo usando exponenciação muito, muito raramente - e estou mais do que feliz em usar uma chamada de método para fazer isso.
fonte
x**2
ex**3
não tão raramente. E uma implementação mágica do pow que o compilador conhece e otimiza para os casos simples seria legal.x * x
ex * x * x
não são maus substitutos para a praça e cubo.x*x
se x é uma expressão. Na melhor das hipóteses, o código se torna pesado e, na pior das hipóteses, mais lento ou até errado. Então, você precisa definir suas próprias funções Square e Cube. E mesmo assim, o código seria mais feio do que usar ** como operador de energia.Os designers da linguagem Java e da biblioteca principal decidiram relegar a maioria das operações matemáticas para a classe Math . Veja Math.pow () .
Por quê? Flexibilidade para priorizar o desempenho em vez de precisão bit a bit. Seria contrário ao resto das especificações de linguagem dizer que o comportamento dos operadores matemáticos internos pode variar de plataforma para plataforma, enquanto a classe Math afirma especificamente que o comportamento potencialmente sacrifica a precisão do desempenho, portanto, cuidado com o comprador:
fonte
A exponenciação fazia parte do Fortran desde o início, porque visava diretamente a programação científica. Engenheiros e físicos costumam usá-lo em simulações, porque as relações com a lei de potência são comuns na física.
O Python também tem uma forte presença na computação científica (por exemplo, NumPy e SciPy). Isso, junto com seu operador de exponenciação, sugere que ele também visava a programação científica.
C, Java e C # têm raízes na programação do sistema. Talvez essa seja uma influência que manteve a exponenciação fora do grupo de operadores suportados.
Apenas uma teoria.
fonte
C definiu apenas operadores para operações aritméticas comuns acessíveis com a ALU. Seu principal objetivo era criar uma interface legível para o código Assembly.
O C ++ não alterou o comportamento de qualquer operador porque desejava que toda a base de código escrita em C fosse compatível.
O Java fez o mesmo porque não queria intimidar os programadores C ++ existentes.
fonte
Bem, porque todo operador que faria sentido para uma energia já está em uso. ^ é XOR e ** define um ponteiro para um ponteiro. Então, em vez disso, eles apenas têm uma função que faz a mesma coisa. (como pow ())
fonte
pow()
função executa seu cálculo em tempo de execução, a menos que você tenha um compilador que possa fazer dobragens constantespow()
, o que duvido muito. (Alguns compiladores dar-lhe a opção de usar intrínsecos do processador para realizar o cálculo, no entanto.)*
é um token lexical, seja usado para indireção ou multiplicação. Uma**
exponenciação de significado seria um ou dois tokens lexicais, e você realmente não deseja que seu lexer tenha que bater na tabela de símbolos para tokenizar.O fato é que operadores aritméticos são apenas atalhos de funções. (Quase) Tudo o que você faz com eles pode ser feito com uma função. Exemplo:
É apenas mais detalhado, então não vejo nada de errado em usar funções para executar 'poder de'.
fonte
Adição / subtração / negação e multiplicação / divisão são operadores matemáticos básicos. Se você tornasse a energia um operador, onde você para? Operador de raiz quadrada? Operador N-root? Operador de logaritmo?
Não posso falar pelos criadores, mas posso dizer que acho que seria complicado e não ortogonal ter esses operadores no idioma. O número de caracteres não alfanuméricos / espaços em branco restantes no teclado é bastante limitado. Como é, é estranho que exista um operador de módulo em C ++.
fonte
mod
um operador é estranho. Geralmente é uma única instrução. É uma operação primitiva em números inteiros. É usado em quase todos os lugares na ciência da computação. (Implementação de coisas como buffers delimitadas semmod
iria feder)