how - sqrt c++
Definiciones de sqrt, sin, cos, pow, etc. en cmath (7)
¿Hay alguna definición de funciones como sqrt()
, sin()
, cos()
, tan()
, log()
, exp()
(estas de math.h / cmath) disponibles?
Solo quería saber cómo funcionan.
Cada implementación puede ser diferente, pero puede verificar una implementación del código fuente de glibc (la biblioteca C de GNU).
editar: Google Code Search se ha desconectado, por lo que el antiguo enlace que tenía no llega a ninguna parte.
Las fuentes para la biblioteca matemática de glibc se encuentran aquí:
Definitivamente echa un vistazo a las fuentes de fdlibm . Son agradables porque la biblioteca fdlibm es autónoma, cada función está bien documentada con explicaciones detalladas de las matemáticas involucradas, y el código es inmensamente claro de leer.
Eche un vistazo a cómo glibc
implementa varias funciones matemáticas, llenas de magia, aproximación y ensamblaje.
Esos casi siempre se implementan como llamadas al sistema. Si quieres ver las fuentes, necesitarás acceder a las fuentes del SO, lo que significa que debes buscar un sistema operativo de código abierto como Linux o BSD.
Esta es una pregunta interesante, pero leer fuentes de bibliotecas eficientes no te llevará muy lejos a menos que conozcas el método utilizado.
Aquí hay algunos consejos para ayudarlo a comprender los métodos clásicos. Mi información no es exacta. Los siguientes métodos son solo los clásicos, las implementaciones particulares pueden usar otros métodos.
- Las tablas de búsqueda se usan con frecuencia
- Las funciones trigonométricas a menudo se implementan a través del algoritmo CORDIC (ya sea en la CPU o con una biblioteca). Tenga en cuenta que generalmente el seno y el coseno se calculan juntos, siempre me pregunté por qué la biblioteca C estándar no proporciona una función
sincos
. - Las raíces cuadradas usan el método de Newton con algunos ingeniosos trucos de implementación: es posible que encuentres en algún lugar de la web un extracto del código fuente de Quake con una implementación de 1 / sqrt (x).
- Los exponenciales y los logaritmos usan exp (2 ^ nx) = exp (x) ^ (2 ^ n) y log2 (2 ^ nx) = n + log2 (x) para tener un argumento cercano a cero (a uno para el registro) y uso aproximación de función racional (generalmente aproximadores de Padé ). Tenga en cuenta que este mismo truco puede obtener exponenciales y logaritmos de la matriz. Según @Stephen Canon, las implementaciones modernas favorecen la expansión de Taylor sobre la aproximación de funciones racionales, donde la división es mucho más lenta que la multiplicación.
- Las otras funciones se pueden deducir de estos. Las implementaciones pueden proporcionar rutinas especializadas.
- pow (x, y) = exp (y * log (x)), por lo que pow no debe usarse cuando y es un entero
- hypot (x, y) = abs (x) sqrt (1 + (y / x) ^ 2) si x> y (hypot (y, x) de lo contrario) para evitar el desbordamiento.
atan2
se calcula con una llamada asincos
y un poco de lógica. Estas funciones son los bloques de construcción para la aritmética compleja. - Para otras funciones trascendentales (gamma, erf, bessel, ...), consulte el excelente libro Numerical Recipes, 3ª edición para algunas ideas. El bueno y viejo Abramowitz & Stegun también es útil. Hay una nueva versión en http://dlmf.nist.gov/ .
- Técnicas como la aproximación de Chebyshev, la expansión continua de fracciones (realmente relacionada con los aproximantes de Padé) o la economización de la serie de potencia se usan en funciones más complejas (si lees, por ejemplo, el código fuente de erf, bessel o gamma). Dudo que tengan un uso real en las funciones simples de matemáticas, pero quién sabe. Consulte las recetas numéricas para obtener una descripción general.
Habiendo mirado mucho el código matemático, aconsejaría no mirar glibc, el código es a menudo bastante difícil de seguir y depende mucho de la magia glibc. La lib de matemáticas en FreeBSD es mucho más fácil de leer, aunque de alguna manera a veces más lenta (pero no por mucho).
Para las funciones complejas, la principal dificultad son los casos fronterizos: el manejo correcto de nan / inf / 0 ya es difícil para las funciones reales, pero es una pesadilla para las funciones complejas. El estándar C99 define muchos casos de esquina, algunas funciones tienen fácilmente 10-20 casos de esquina. Puede ver el anexo G del documento estándar C99 actualizado para tener una idea. También es difícil con el doble largo, porque su formato no está estandarizado; en mi experiencia, debe esperar bastantes errores con el doble largo. Con suerte, la próxima versión revisada de IEEE754 con precisión ampliada mejorará la situación.
La mayoría del hardware moderno incluye unidades de coma flotante que implementan estas funciones de manera muy eficiente.