Perdona la ingenuidad que será obvia en la forma en que hago esta pregunta, así como el hecho de que la estoy haciendo.
Los matemáticos suelen usar ya que es la base más simple / mejor en teoría (debido al cálculo). Pero las computadoras parecen hacer todo en binario, entonces, ¿es más rápido en una máquina para calcular que ?2**x
Math::exp(x)
binary-arithmetic
numerical-analysis
numeral-representations
isomorfismos
fuente
fuente
Respuestas:
Como se trata de CS y no de Stackoverflow, voy a suponer que está haciendo una pregunta sobre el análisis numérico y (para simplificar) el punto flotante IEEE-754 en particular. En ese caso, la respuesta a su pregunta depende en parte de lo que quiere decir con "más fácil", y en parte de los detalles del sistema.
No conozco ninguna CPU moderna que tenga una instrucción integrada que haga exactamente lo que esperaría, ya sea para la operación (que en adelante llamaremos , su nombre habitual en C) o ( ). Ambos se implementan utilizando funciones de biblioteca.ex 2x
exp
exp2
Como es el caso con todos los métodos numéricos para operaciones trascendentales, hay algunos casos especiales a considerar:
Sin embargo, hay otra cosa que hace que el problema sea un poco menos complicado: el dominio útil es bastante pequeño. Para binary32, sex<−104 x>88.7
exp(x)
desborda si o menos, y se desborda si o menos. Inusualmente para operaciones trascendentales, también podemos ignorar el caso subnormal, ya que es indistinguible de si es subnormal. Todo lo anterior también es cierto , excepto que el dominio es ligeramente diferente.exp(x)
1.0
x
exp2
Su intuición es correcta en que la mayoría de las implementaciones calculan . Sin embargo, el costo de esa multiplicación por es trivial en comparación con el resto de la informática . Un método típico utiliza una tabla calculada previamente con elementos :ex=2x/ln2 1ln2 K
exp2
donde es la parte entera de , la tabla contiene valores de para todo en el rango , y es una aproximación polinómica a (cuarto es suficiente para binario32 ) en el rango . La parte es barata, ya que solo está manipulando el exponente. es una tabla de búsqueda. Por lo tanto, es probable que sea la parte costosa de la operación.n x T 2j/K j [0,K) P 2x 2nTP[0,1K) 2n T P
Debo señalar para completar que las FPU Intel x86 incluyen una instrucción llamada2x−1 x [−1,1]
f2xm1
, que calcula para en el rango . Sin embargo, en una CPU moderna, esta es una instrucción bastante costosa y no canalizada, y no se recomienda utilizarla. Como señala correctamente la Sección 3.8.5 del Manual de referencia de Intel Optimization :x [ - 1 , 1 ]Editar: Se ha señalado en los comentarios que debería explicar algo de la nueva terminología utilizada en IEEE 754-2008. Parte del lenguaje ha cambiado desde 1985 y 1987, y la mayoría de las personas están mucho más familiarizadas con la antigua jerga.
Los términos "binary32" y "binary64" son los nuevos nombres para los números de coma flotante binarios de 32 y 64 bits, que el estándar anterior llamaba "single" y "double" respectivamente.
El término "número subnormal" reemplaza el término anterior "número denormal" o "número desnormalizado" .
fuente
Si2x
2**x
quiere decir , entonces sí. Podemos usar el operador de desplazamiento a la izquierda , es decir, calculamos . Esto es increíblemente rápido, ya que es una instrucción de máquina primitiva en todos los procesadores que conozco. Esto no se puede hacer con ninguna base que no sea 2. Además, la exponenciación de enteros siempre será más rápida que la exponenciación real, ya que los números de coma flotante tardan más en multiplicarse.<<
1 << x
fuente
x
no es un número entero (digamos20.75
), establecería la mantisa2
y el exponente en el valor redondeado dex
la estimación más precisa (no es posible la representación precisa). Lo cual también es mucho más rápido que `pow´.Si
2**x
es una función en enteros, entonces estoy de acuerdo con la respuesta de Stephen, shift es más barato. Pero típicamente veo eso como2^x
y**
para indicar exponenciación de punto flotante. Para este caso, esperaría un rendimiento similar entre**
y^
ya que ambosexp
ypow
(la operación subyacente para**
) son operaciones de aproximación trascendentales.fuente
**
se consideraba un sinónimo de la versión de punto flotante (y, tontamente, había olvidado que las dos serían diferentes).Dado que 2 ^ x = e ^ (x * ln 2) y e ^ x = 2 ^ (x * log2 (e)), no esperaría mucha diferencia.
Para x cercano a cero, generalmente se usaría un polinomio e ^ x = 1 + x + x ^ 2/2 + x ^ 3/6 ..., muy bien optimizado para cortar lo antes posible mientras se mantiene pequeño el error de redondeo . Claramente, 2 ^ x es un poco, un poquito más lento de calcular. "x cerca de 0" generalmente serían valores de x donde sqrt (1/2) <= e ^ x <= sqrt (2). Restringir el rango de x asegura que el grado polinómico no tenga que elegirse demasiado alto.
Para x más grande, generalmente se calcularía 2 ^ x dejando x = x '+ x' ', donde x' es un número entero y -0.5 <= x '' <= 0.5. Entonces 2 ^ x 'se calcularía construyendo un número de coma flotante con el patrón de bits correcto, y 2 ^ x' 'usando el método e ^ x para x pequeño. Aquí, 2 ^ x es un poquito más rápido. Además, si x es grande (digamos x = 100.3), solo multiplicar x por log2 (e) introduciría un error de redondeo inaceptable (porque hay muchos menos bits fraccionarios), por lo que se debe tener más cuidado.
Y con suerte, una buena función de biblioteca se encargaría de que siempre que x <= y, e ^ x <= e ^ y y 2 ^ x <= 2 ^ y, sin importar cuáles sean los errores de redondeo. Lograr ese tipo de cosas puede ser complicado.
fuente
Debe comprender que las matemáticas en una computadora se realizan de diferentes maneras por diferentes programas, con la esperanza de obtener respuestas consistentes. En cuanto a la mayoría del software, creo que las computadoras se comportan bien: las computadoras y calcularán la respuesta a la larga, incluso para 0 ^ 0. El problema es que los casos especiales involucran "reconocimiento" que no ocurre de forma gratuita en las computadoras digitales. Esto significa que solo en aquellos casos en que tener la respuesta acelerará las cosas "al máximo" se producirá la optimización. Pero en esos casos ocurrirá extremadamente bien. También tenga en cuenta que se deben hacer varios reconocimientos diferentes para obtener la respuesta correcta. Esto se llama niveles de optimización de velocidad y esto ha ocurrido en la máxima medida profesional en base a la mayoría del software llamado GNU "C". Esto se debe a que aquí se utilizan pequeñas diferencias en el tiempo de ejecución de software a software y de máquina a máquina como cifras de aceptación de calidad. En otros intérpretes, por lo general, solo si se produce un "indicador cero" como efecto secundario de los cálculos anteriores, se acelerará el reconocimiento. como 0 * x => C0.
fuente