Có một sự khác biệt quan trọng giữa std::min, std::maxvà fminvà fmax.
std::min(-0.0,0.0) = -0.0
std::max(-0.0,0.0) = -0.0
trong khi
fmin(-0.0, 0.0) = -0.0
fmax(-0.0, 0.0) = 0.0
Vì vậy, std::minkhông phải là thay thế 1-1 cho fmin. Các hàm std::minvà std::maxkhông có tính chất giao hoán. Để nhận được cùng một kết quả với các nhân đôi với fminvà fmaxmột người nên hoán đổi các đối số
fmin(-0.0, 0.0) = std::min(-0.0, 0.0)
fmax(-0.0, 0.0) = std::max( 0.0, -0.0)
Nhưng theo như tôi có thể nói tất cả các chức năng này dù sao cũng được xác định trong trường hợp này, vì vậy để chắc chắn 100%, bạn phải kiểm tra xem chúng được thực hiện như thế nào.
Có một sự khác biệt quan trọng khác. Đối với x ! = NaN:
std::max(Nan,x) = NaN
std::max(x,NaN) = x
std::min(Nan,x) = NaN
std::min(x,NaN) = x
trong khi
fmax(Nan,x) = x
fmax(x,NaN) = x
fmin(Nan,x) = x
fmin(x,NaN) = x
fmax có thể được mô phỏng bằng đoạn mã sau
double myfmax(double x, double y)
{
int xnan = isnan(x), ynan = isnan(y);
if(xnan || ynan) {
if(xnan && !ynan) return y;
if(!xnan && ynan) return x;
return x;
}
if(x==0 && y==0) {
int xs = signbit(x), ys = signbit(y);
if(xs && !ys) return y;
if(!xs && ys) return x;
return x;
}
return std::max(x,y);
}
Điều này cho thấy đó std::maxlà một tập hợp con của fmax.
Nhìn vào assembly cho thấy Clang sử dụng mã nội trang fmaxvà fmintrong khi GCC gọi chúng từ thư viện toán học. Cụm cho tiếng kêu fmaxvới -O3là
movapd xmm2, xmm0
cmpunordsd xmm2, xmm2
movapd xmm3, xmm2
andpd xmm3, xmm1
maxsd xmm1, xmm0
andnpd xmm2, xmm1
orpd xmm2, xmm3
movapd xmm0, xmm2
trong khi đối với std::max(double, double)nó đơn giản là
maxsd xmm0, xmm1
Tuy nhiên, đối với GCC và Clang, việc sử dụng -Ofast fmaxtrở nên đơn giản
maxsd xmm0, xmm1
Vì vậy, điều này cho thấy một lần nữa đó std::maxlà một tập hợp con của fmaxvà khi bạn sử dụng mô hình dấu phẩy động lỏng hơn mà không có nanhoặc có dấu không thì fmaxvà std::maxgiống nhau. Đối số tương tự rõ ràng áp dụng cho fminvà std::min.