usar round ejemplos clase c# .net pow

round - math.sqrt c#



¿Cómo se implementa Math.Pow() en.NET Framework? (3)

MethodImplOptions.InternalCall

Eso significa que el método se implementa realmente en el CLR, escrito en C ++. El compilador justo a tiempo consulta una tabla con métodos implementados internamente y compila la llamada a la función C ++ directamente.

Mirar el código requiere el código fuente para el CLR. Usted puede obtener eso de la distribución SSCLI20 . Fue escrito alrededor del marco de tiempo de .NET 2.0, encontré que las implementaciones de bajo nivel, como Math.Pow() siguen siendo bastante precisas para las versiones posteriores del CLR.

La tabla de búsqueda se encuentra en clr / src / vm / ecall.cpp. La sección que es relevante para Math.Pow() ve así:

FCFuncStart(gMathFuncs) FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin) FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos) FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt) FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round) FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs) FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs) FCFuncElement("Exp", COMDouble::Exp) FCFuncElement("Pow", COMDouble::Pow) // etc.. FCFuncEnd()

La búsqueda de "COMDouble" le lleva a clr / src / classlibnative / float / comfloat.cpp. Te ahorraré el código, solo échale un vistazo. Básicamente verifica los casos de esquina, luego llama a la versión de CRT de pow() .

El único otro detalle de implementación que es interesante es la macro FCIntrinsic en la tabla. Eso es un indicio de que el jitter puede implementar la función como un intrínseco. En otras palabras, sustituya la llamada de función con una instrucción de código de máquina de punto flotante. Lo que no es el caso de Pow() , no hay instrucciones FPU para ello. Pero sin duda para las otras operaciones simples. Notable es que esto puede hacer que las matemáticas de punto flotante en C # sean sustancialmente más rápidas que el mismo código en C ++, verifique esta respuesta por la razón.

Por cierto, el código fuente de CRT también está disponible si tiene la versión completa del directorio Visual Studio vc / crt / src. Sin embargo, golpearás la pared en pow() , Microsoft compró ese código de Intel. Hacer un mejor trabajo que los ingenieros de Intel es poco probable. Aunque la identidad de mi libro de la escuela secundaria era dos veces más rápida cuando lo probé:

public static double FasterPow(double x, double y) { return Math.Exp(y * Math.Log(x)); }

Pero no es un sustituto real porque acumula el error de 3 operaciones de punto flotante y no se ocupa de los problemas de dominios raros que tiene Pow (). Como 0 ^ 0 e -Infinito elevado a cualquier potencia.

Estaba buscando un enfoque eficiente para calcular a b (por ejemplo, a = 2 y b = 50 ). Para empezar, decidí echar un vistazo a la implementación de la función Math.Pow() . Pero en .NET Reflector , todo lo que encontré fue esto:

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical] public static extern double Pow(double x, double y);

¿Cuáles son algunos de los recursos en los que puedo ver lo que ocurre dentro de la función Math.Pow() ?



La respuesta de Hans Passant es excelente, pero me gustaría agregar que si b es un número entero, a^b se puede calcular de manera muy eficiente con descomposición binaria. Aquí hay una versión modificada de Henry Warren''s Hacker''s Delight :

public static int iexp(int a, uint b) { int y = 1; while(true) { if ((b & 1) != 0) y = a*y; b = b >> 1; if (b == 0) return y; a *= a; } }

Señala que esta operación es óptima (hace el número mínimo de operaciones aritméticas o lógicas) para todas las b <15. Además, no se conoce ninguna solución al problema general de encontrar una secuencia óptima de factores para calcular a^b para cualquier otra b que una extensa búsqueda. Es un problema NP-Hard. Así que, básicamente, eso significa que la descomposición binaria es tan buena como es posible.