自制C语言与x86汇编版fabs函数的精度问题排查
Why the Discrepancy Happens
The difference comes down to three key factors:
189.55 isn't exactly representable as a 32-bit float
Binary floating-point numbers can't represent all decimal fractions exactly. The closest 32-bit float to 189.55 is189.5500030517578125—this is the actual value stored when you write189.55f. Your custom functions (fabs1,fabs2,fabs3) all return this exact float value, which when printed with 6 decimal places shows as189.550003.The standard
fabsfunction uses double-precision
Thefabsfunction operates ondoublevalues. When you pass afloatliteral like-189.55ftofabs, the compiler may optimize the constant expression to use the closestdoubleto 189.55 instead of converting the float value to double. The closest double to 189.55 is189.5499999999999886..., which rounds to189.550000when printed with 6 decimal places.You're comparing float functions to a double function
Your custom functions returnfloat, but you're comparing them tofabs(which returnsdouble). The standard float equivalent isfabsf—if you usefabsf(-189.55f), it will return the same float value as your functions, leading to matching output.
How to Fix the Output
If you want all outputs to match, you have a few options:
1. Use the standard float function (fabsf)
Replace fabs with fabsf in your printf call. This ensures you're comparing apples to apples (float-to-float):
printf("fabsf(-189.55f) = %f\n", fabsf(-189.55f));
This will output 189.550003, matching your custom functions.
2. Avoid constant folding with a variable
If you use a variable instead of a literal, the compiler can't optimize the fabs call to use a double literal. The float value will be converted to double normally, resulting in the same output as your functions:
float x = -189.55f; printf("fabs(x) = %f\n", fabs(x)); // Outputs 189.550003
3. Print with rounded precision
If you want to display the value as 189.550000 regardless of the exact floating-point representation, use a format specifier that rounds to fewer decimal places. For example:
printf("fabs1(-189.55f) = %.2f\n", fabs1(-189.55f)); // Outputs 189.55 // Or to keep 6 decimal places but round: printf("fabs1(-189.55f) = %.6f\n", roundf(fabs1(-189.55f) * 1e6) / 1e6);
Note that this changes the displayed value, not the actual floating-point value stored.
Key Takeaway
Your custom fabs implementations are working correctly—they return the exact absolute value of the float input. The discrepancy is just an artifact of how the compiler optimizes constant expressions and the difference between float and double precision.
内容的提问来源于stack exchange,提问作者Cuco

