¿Por qué no hay un operador de energía en Java / C ++?

Si bien existe ese operador – ** en Python, me preguntaba por qué Java y C ++ no tienen uno también.

Es fácil crear uno para las clases que defina en C ++ con sobrecarga de operadores (y creo que eso también es posible en Java), pero cuando se habla de tipos primitivos como int, double y así sucesivamente, tendrás que usar la función de biblioteca como Math.power (y normalmente tendrás que convertir ambas para duplicar).

Entonces, ¿por qué no definir ese operador para tipos primitivos?

Comentarios

  • En C ++, no podemos crear nuestros propios operadores. Solo puede sobrecargar los operadores existentes.
  • @Mahesh, por lo que puedo crear mi propia clase de número y sobrecargar ^ operador para que sea una potencia. Eso realmente no importa.
  • @RanZilber: Sí importa porque la precedencia del operador ^ no coincide con la precedencia de la exponenciación. Considere la expresión a + b ^ c. En matemáticas, la potenciación se realiza primero (b ^ c), luego la potencia resultante se suma a a. En C ++, la adición se realiza primero (a + b) y luego el operador ^ se realiza con c. Entonces, incluso si implementó el operador ^ para significar exponenciación, la precedencia sorprenderá a todos.
  • @RamZilber – ^ es un XOR en C ++. Se aconseja que el operador sobrecargado no debería hacer nada diferente a lo que hace un tipo de datos primitivo al usarlo.
  • @RanZilber: Porque ‘ no es nada intuitivo de usar cualquiera de esos operadores que mencione significa exponenciación. Yo cuestionaría seriamente la competencia de cualquier programador de C ++ que sobrecargue el operador ++ o el operador ! et. Alabama. para significar exponenciación. Pero puede ‘ t de todos modos, porque los operadores de los que habla aceptan sólo un argumento; la exponenciación requiere dos argumentos.

Respuesta

En términos generales, los operadores primitivos en C (y por extensión C ++) están diseñados para ser implementados por hardware simple en aproximadamente una sola instrucción. Algo como la potenciación a menudo requiere soporte de software; por lo que no está ahí de forma predeterminada.

Además, es proporcionado por la biblioteca estándar del idioma en la forma de std::pow.

Por último, hacer esto para tipos de datos enteros no tendría mucho sentido, porque la mayoría de los valores pequeños para la exponenciación superan el rango requerido para int, que es hasta 65 535. Claro, podría hacer esto para dobles y flotantes, pero no ints, pero ¿por qué hacer que el lenguaje sea inconsistente para una función que se usa con poca frecuencia?

Comentarios

  • Si bien estoy de acuerdo con la mayor parte de esto, el hecho de que el módulo El operador no se puede usar en tipos de punto flotante es inconsistente para tipos de datos primitivos, pero eso también probablemente no sería una sola instrucción en ningún hardware que imagino prevalezca ahora.
  • @Sion: Al menos en x86, el módulo es una sola instrucción. (DIV hace tanto la división como el módulo) Sin embargo, ‘ me tienes en el punto de consistencia.
  • @Billy ONeal: Mod de coma flotante lus en una sola instrucción? Últimamente, no he ‘ t andado en la asamblea para saberlo por mí mismo. Si ese ‘ es el caso, entonces el operador de módulo debería ser aplicable a los tipos de punto flotante.
  • @DonalFellows: FORTRAN tenía el operador de exponenciación mucho antes que cualquier cosa que se parezca al soporte de bignum.
  • @DonalFellows: Un operador de potencia no es ‘ t tan útil con enteros como con flotantes, pero para potencias pequeñas (especialmente cuadradas) podría definitivamente tiene sus usos. Personalmente, me gusta el enfoque de hacer operadores con letras (como lo hace Pascal con div o FORTRAN con .EQ.); dependiendo de las reglas de espacios en blanco del idioma, puede ser posible tener un número arbitrario de operadores sin requerir que sean palabras reservadas.

Respuesta

Esta pregunta se puede responder para C ++: Stroustrup,» Diseño y evolución de C ++ «analiza esto en la sección 11.6.1, pp. 247-250.

Hubo objeciones generales a agregar un nuevo operador. Se sumaría a la ya complicada tabla de precedencia. Los miembros del grupo de trabajo pensaron que solo les daría una pequeña conveniencia sobre tener una función, y querían poder sustituir sus propias funciones a veces.

No había un buen candidato para un operador.^ es exclusivo-or, y ^^ provocó confusión debido a la relación entre & y | y && y ||. ! no era adecuado ya que habría una tendencia natural a escribir != para exponenciar un valor existente, y eso ya se tomó. El mejor disponible puede haber sido *^, que aparentemente a nadie realmente le gustó.

Stroustrup consideró ** nuevamente, pero ya tiene un significado en C: a**p es a veces lo que p apunte, y char ** c; declara c como un puntero al puntero a char. Presentamos ** como un token que significa «declaración de un puntero al puntero a», «multiplicado por lo que apunta el próximo» (si es «un puntero) o» exponenciación «(si se sigue por un número) causó problemas de precedencia. a/b**p tendría que analizar como a/(b**p) si p fuera un número, pero (a/b) * *p si p fuera un puntero, esto tendría que resolverse en el analizador.

En otras palabras, habría sido posible, pero habría complicado la tabla de precedencia y la analizador, y ambos ya son demasiado complicados.

No conozco la historia sobre Java; todo lo que podría hacer sería especular. En cuanto a C, donde comenzó, todos los operadores de C se traducen fácilmente a código ensamblador, en parte para simplificar el compilador y en parte para evitar ocultar funciones que consumen mucho tiempo en operadores simples (el hecho de que operator+() y otros podían ocultar una gran complejidad y los golpes de rendimiento fue una de las primeras quejas sobre C ++).

Comentarios

  • Buena respuesta. Supongo que Java intentó simplificar C a este respecto, por lo que nadie quería agregar un nuevo operador. Eso ‘ es una pena que nadie me preguntara, seguro que me hubiera gustado *^. : D
  • C fue creado para dar formato a texto. Fortran fue construido para hacer matemáticas y tenía matemáticas complejas, de potencia y de matriz 20 años antes.
  • @Martin Beckett: ¿Puedes encontrar evidencia de que C fue construido para formatear texto? Me parece un lenguaje muy torpe para eso, y lo que ‘ he leído sobre el origen de C dice que fue diseñado principalmente para programación de sistemas para Unix.
  • @DavidThornley – Fue diseñado para escribir Unix en, pero todos los primeros usos de Unix parecen haber sido el formato de texto, y por eso ‘ s tiempo tiene una cadena extensa y i / o biblioteca.
  • +1: El significado existente para a**p es el asesino. (Los trucos para solucionar ese problema … ¡Brr!)

Responder

Yo sospecho es porque cada operador que introduce aumenta la complejidad del idioma. Por lo tanto, la barrera de entrada es muy alta. Me encuentro usando exponenciación muy, muy raramente, y estoy más que feliz de usar una llamada a método para hacer entonces.

Comentarios

  • Cada característica comienza con -100 puntos.
  • Yo ‘ d uso x**2 y x**3 no tan raramente . Y una implementación de pow mágico que el compilador conozca y optimice para los casos simples estaría bien.
  • @CodeInChaos: Sin embargo x * x y x * x * x aren ‘ t malos sustitutos para el cuadrado y el cubo.
  • @David puedes ‘ t simplemente escribe x*x si x es una expresión. En el mejor de los casos, el código se vuelve difícil de manejar y, en el peor, más lento o incluso incorrecto. Entonces, ‘ d necesita definir sus propias funciones Cuadrado y Cubo. E incluso entonces el código sería más feo que usar ** como operador de poder.
  • @David Necesito poner entre paréntesis sí, pero no ‘ no es necesario repetir la expresión varias veces y sobrecarga el código fuente. Lo que reduce mucho la legibilidad. Y la eliminación de subexpresiones comunes solo es posible si el compilador puede garantizar que la expresión esté libre de efectos secundarios. Y al menos .net jitter no es ‘ demasiado inteligente en ese sentido.

Respuesta

Los diseñadores de la biblioteca principal y del lenguaje Java decidieron relegar la mayoría de las operaciones matemáticas a la clase Math . Consulte Math.pow () .

¿Por qué? Flexibilidad para priorizar el rendimiento sobre la precisión bit a bit.Sería contrario al resto de la especificación del lenguaje decir que el comportamiento de los operadores matemáticos integrados podría variar de una plataforma a otra, mientras que la clase Math establece específicamente que el comportamiento potencialmente sacrifica la precisión por el rendimiento, por lo que el comprador debe tener cuidado:

A diferencia de algunos de los métodos numéricos de la clase StrictMath , todas las implementaciones de las funciones equivalentes de la clase Las matemáticas no están definidas para devolver los mismos resultados bit a bit. Esta relajación permite implementaciones de mejor rendimiento donde no se requiere una reproducibilidad estricta.

Responder

La exponenciación fue parte de Fortran desde el principio porque estaba dirigida directamente a la programación científica. Los ingenieros y físicos lo usan a menudo en simulaciones, porque las relaciones de la ley de potencia son comunes en física.

Python también tiene una fuerte presencia en la informática científica (por ejemplo, NumPy y SciPy). Eso, junto con su operador de potenciación, sugiere que también estaba destinado a la programación científica.

C, Java y C # tienen sus raíces en la programación de sistemas. Quizás esa es una influencia que mantuvo la exponenciación fuera del grupo de operadores admitidos.

Solo una teoría.

Respuesta

Operadores definidos por C solo para operaciones aritméticas comunes accesibles con la ALU. Su objetivo principal era crear una interfaz legible por humanos para el código Ensamblador.

C ++ no cambió el comportamiento de ningún operador porque quería todo el código base escrito en C debe ser compatible.

Java hizo lo mismo porque no quería intimidar a los programadores de C ++ existentes.

Comentarios

  • Cuando se creó C, la multiplicación y la división no faltaban con frecuencia en el hardware y tenían que implementarse en el software. Sin embargo, C tiene operadores de multiplicación y división.
  • @siride: Que yo sepa, el PDP-7, la primera computadora en ejecutar Unix, tenía multiplicación y división de hardware a través de su EAE. Consulte: bitsavers.org/pdf/dec/pdp7/F-75_PDP-7userHbk_Jun65.pdf

Respuesta

Bueno, porque todos los operadores que tengan sentido para una potencia ya están en uso. ^ es XOR y ** define un puntero a un puntero. Entonces, en cambio, solo tienen una función que hace lo mismo. (como pow ())

Comentarios

  • @RTS – ¿Un desarrollador de idiomas realmente busca más sentido que eficiencia?
  • Un buen desarrollador de un lenguaje de programación se fija en ambos. No puedo ‘ decir nada sobre Java. Pero en c ++ la función pow () se calcula en tiempo de compilación. Y es tan eficiente como los operadores regulares.
  • @RTS: La función pow() realiza su cálculo en tiempo de ejecución, a menos que tenga un compilador que pueda realizar un plegado constante para pow(), que dudo mucho. (Sin embargo, algunos compiladores le dan la opción de usar componentes intrínsecos del procesador para realizar el cálculo).
  • @En silico, no ‘ quise decir que calcula la value, quise decir que los compiladores optimizarán la llamada a la función, por lo que solo tiene la ecuación en bruto.
  • @josefx: Seguro que ‘ es una buena razón. Un solo * es un token léxico, ya sea que ‘ se use para indirección o multiplicación. Un ** que significa exponenciación sería uno o dos tokens léxicos, y realmente no ‘ no quiere que su lexer tenga que presionar el símbolo tabla para tokenizar.

Respuesta

El hecho es que los operadores aritméticos son solo atajos de funciones. (Casi) Todo lo que haces con ellos se puede hacer con una función. Ejemplo:

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

Es más detallado, así que no veo nada de malo en usar funciones para realizar el «poder de».

Respuesta

Suma / resta / negación y multiplicación / división son operadores matemáticos básicos. Si tuvieras que hacer de la potencia un operador, ¿dónde te detendría? Raíz cuadrada ¿Operador? ¿Operador de raíz N? ¿Operador de logaritmo?

No puedo hablar por sus creadores, pero puedo decir que creo que sería difícil de manejar y no ortogonal tener tales operadores en el lenguaje. el número de caracteres no alfanuméricos / espacios en blanco que quedan en el teclado es bastante limitado. Tal como está, es extraño que haya un operador de módulo en C ++.

Comentarios

  • +1 – No ‘ no veo por qué tener mod como operador es extraño. Es ‘ suele ser una sola instrucción. Es ‘ una operación primitiva con números enteros. Es ‘ s se utilizan en la mayoría de los casos en informática.(Implementar cosas como búferes limitados sin mod apestaría)
  • @Billy ONeal: extraño debido a la inconsistencia entre poder usar con tipos enteros y tipos de punto flotante . Sin embargo, es absolutamente útil y no ‘ soñaría con eliminarlo. Simplemente peculiar es todo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *