.net math double type-conversion reflector

.net - math.min c#



Implementación.NET: conversión doble en Math.Min(float, float) (4)

Sí, utilicé Resharper, que hace exactamente eso

Y ese es el problema, busca el código. El código fuente está disponible desde la fuente de referencia , se ve así:

[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static float Min(float val1, float val2) { if (val1 < val2) return val1; if (Single.IsNaN(val1)) return val1; return val2; }

Es difícil adivinar por qué Resharper hace esto, supongo que es solo un error. Favorece el código fuente disponible de Microsoft, no solo por precisión, sino que los comentarios también son agradables.

¿Por qué .Net implementa la función Math.Min (float, float) así:

public static float Min(float val1, float val2) { if ((double) val1 < (double) val2 || float.IsNaN(val1)) return val1; else return val2; }

Si bien puedo ver el uso de IsNaN, no entiendo por qué se convierten a doble cuando se comparan los valores. ¿No es más lento que simplemente escribir val < val 2 ? Especialmente si quería usarlo para fijar un valor a los números sin mucha precisión como 0f o 1f .

¿Debo seguir adelante e implementar una biblioteca matemática personalizada que también requiera tener valores que no sean de NaN para obtener el mejor rendimiento o es una pérdida de tiempo?

public static float Min(float a, float b) { return a < b ? a : b; }


En general, no puede suponer que Single realiza más rápido que Double . Los registros de coma flotante en las CPU de Intel son de 80 bits y las operaciones de punto flotante en la CPU se realizan usando esa precisión. En esa plataforma, el JIT puede generar instrucciones de coma flotante que cargan los argumentos en los registros nativos de 80 bits y la única diferencia es si los registros se cargan desde ubicaciones de memoria de 32 bits o 64 bits. Quizás los implementadores de Math.Min basaron su implementación en un conocimiento complejo de cómo el compilador JIT genera código de coma flotante.

A partir de la respuesta aceptada, se puede ver que la pregunta se basa en la suposición errónea (que hay un elenco de Single a Double ). Para investigar si el yeso realmente hace la diferencia, miré al ensamblador generado por una función Min con y sin un molde.

Este es el .NET Framework Math.Min(Single, Single) como se ve en mi depurador:

00000000 push ebp 00000001 mov ebp,esp 00000003 fld dword ptr [ebp+0Ch] 00000006 fld dword ptr [ebp+8] 00000009 fxch st(1) 0000000b fcomi st,st(1) 0000000d jp 00000015 0000000f jae 00000015 00000011 fstp st(1) 00000013 jmp 00000022 00000015 fcomi st,st(0) 00000017 jp 0000001B 00000019 je 00000026 0000001b mov eax,1 00000020 jmp 00000028 00000022 pop ebp 00000023 ret 8 00000026 xor eax,eax 00000028 test eax,eax 0000002a je 00000030 0000002c fstp st(1) 0000002e jmp 00000036 00000030 fstp st(0) 00000032 pop ebp 00000033 ret 8 00000036 pop ebp 00000037 ret 8

Aquí está el ensamblaje de una función que usa un molde para Double al igual que en la pregunta:

00000000 push ebp 00000001 mov ebp,esp 00000003 sub esp,8 00000006 fld dword ptr [ebp+0Ch] 00000009 fld dword ptr [ebp+8] 0000000c fld st(1) 0000000e fstp qword ptr [ebp-8] 00000011 fld qword ptr [ebp-8] 00000014 fld st(1) 00000016 fstp qword ptr [ebp-8] 00000019 fld qword ptr [ebp-8] 0000001c fcomip st,st(1) 0000001e fstp st(0) 00000020 jp 00000028 00000022 jbe 00000028 00000024 fstp st(0) 00000026 jmp 00000043 00000028 fxch st(1) 0000002a fcomi st,st(0) 0000002c jp 00000030 0000002e je 00000037 00000030 mov eax,1 00000035 jmp 00000039 00000037 xor eax,eax 00000039 test eax,eax 0000003b jne 00000041 0000003d fstp st(0) 0000003f jmp 00000049 00000041 fstp st(1) 00000043 mov esp,ebp 00000045 pop ebp 00000046 ret 8 00000049 mov esp,ebp 0000004b pop ebp 0000004c ret 8

Hay algunas instrucciones más y probablemente disminuirán ligeramente el rendimiento de la función.



No puedo decirte por qué eligieron lanzar float para double para la comparación, pero dudo que vaya a causar un impacto de velocidad notable o significativo en tu programa. Solo usaría la función incorporada.