Реализация .NET: двойное преобразование в математике.Мин (поплавок, поплавок)
Почему .Net реализует математику.Функция Min (float, float) выглядит так:
public static float Min(float val1, float val2)
{
if ((double) val1 < (double) val2 || float.IsNaN(val1))
return val1;
else
return val2;
}
Хотя я вижу использование IsNaN, я не понимаю, почему они преобразуются в double при сравнении значений. Разве это не медленнее, чем просто писать val < val 2
? Особенно если я хотел использовать его, чтобы закрепить значение в числах без особой точности, как 0f
или 1f
.
Должен ли я просто пойти вперед и реализовать пользовательскую математическую библиотеку, которая дополнительно также требует иметь значения non NaN, чтобы получить лучшее представление или это пустая трата времени?
public static float Min(float a, float b)
{
return a < b ? a : b;
}
4 ответа:
Да, я использовал Resharper, который делает именно это
И вот в чем проблема, он путается в коде. Исходный код доступен из справочного источника , он выглядит следующим образом:
Трудно догадаться, почему Решарпер делает это, я бы с готовностью предположил, что это просто ошибка. Отдавайте предпочтение исходному коду, доступному от Microsoft, не только для точности, но и комментарии тоже хороши.[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; }
Я не могу сказать вам, почему они решили бросить
float
вdouble
Для сравнения, но я сомневаюсь, что это вызовет какое-либо заметное или значительное влияние скорости на вашу программу. Я бы просто использовал встроенную функцию.
Нет такой вещи, как математика.Мин(поплавок, поплавок). .NET содержит только определение для Min (double, double). Проверьте MSDN: http://msdn.microsoft.com/en-us/library/system.math.min (v=против 100).aspx
EDIT: есть, спасибо @gideon http://msdn.microsoft.com/en-us/library/070xee48.aspx
В общем случае нельзя считать, что
Из принятого ответа видно, что вопрос основан на неверном предположении (что существует приведение отSingle
работает быстрее, чемDouble
. Регистры с плавающей запятой на процессоре Intel составляют 80 бит, и операции с плавающей запятой на процессоре выполняются с использованием этой точности. На этой платформе JIT может генерировать команды с плавающей запятой, которые загружают аргументы в собственные 80-битные регистры, и единственная разница заключается в том, что регистры загружаются из 32-битных или 64-битных ячеек памяти. Возможно, исполнителиMath.Min
основывали свою реализацию на сложные знания о том, как JIT-компилятор генерирует код с плавающей запятой.Single
кDouble
). Чтобы выяснить, действительно ли приведение имеет значение, я посмотрел на ассемблер, сгенерированный функциейMin
с приведением и без приведения.Это .NET framework
Math.Min(Single, Single)
, как показано в моем отладчике: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Вот сборка для функции, использующей приведите к
Double
точно так же, как в вопросе: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Есть еще несколько инструкций, и они, вероятно, немного снизят производительность функции.