The value reported by float.Epsilon isn't actually Epsilon.
According to documentation (and confirmed by experiment), Single.Epsilon has a value of 1.4E-45, which is the (as the documentation states) "the smallest positive Single greater than zero.".
Compare that to C where
float.h:
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0 */
and C++, where std::numeric_limits<float>::epsilon() is "the difference between 1 and the smallest value greater than 1 that is representable for the data type".
<grumpy off topic aside> epsilon has special meaning within the ANSI/IEEE 754 standard for floating point arthmetic. The C# convention varies sharply from common usage and standard convention. And non-conformance with ANSI/IEEE 754 is not a small issue for a modern computer language. This is basic numeric analysis 101 stuff, and a mistake like this is pretty inexcusable. It makes me gravely concerned about the validity of the rest of the floating point implementation in .net. The C++ version of epsilon is intensely useful, but I can't honestly thing of a single use for the CLR version of epsilon. And the stated intended usage in the documentation for Single.Epsilon is just plain wrong. Single.Epsilon, as currently defined absolutely cannot be used for any reasonable version of soft floating point comparison.</grumpy off topic aside>.
So. Back to the real question. Is there a standard place in CLR where I can get the real machine epsilon (defined as the smallest float for which 1.0f+epsilon != 1.0f) for float
<more grumpy off-topic aside> It's actually interesting how difficult it is to calculate FLOAT_EPSILON at runtime due to the oddities of Single and Double float operations on x86. I really don't like hard-coding this value.</more grumpy off-topic aside>

single.Epsilon isn't.
Softpen
My test was to gage whether Epsilon can be used to accurately compare specific floating-point values to calculated representations. I found the rounding error to be significantly larger than the Epsilon values of Single and Double.
I've found the FLT_EPSILON value to be as equally unfitting as the Single.Epsilon. In the following example, neither FLT_EPSILON (as defined in the ANSI C) nor Single.Epilon accurately allows me to tell if the result of the calculation is "equal enough":
float price = 4.99f;
int quantity = 17;
float total = price * (float)quantity;
float expected = 84.83f;
float difference = Math.Abs(total - expected);
if (float.Epsilon >= difference)
{
System.Diagnostics.Debug.WriteLine("Values essential equal");
}
const float FLT_EPSILON = 1.192092896e-07F;
if (FLT_EPSILON >= difference)
{
System.Diagnostics.Debug.WriteLine("Values essential equal");
}
I think either value is academic. C epsilon is defined as "as the difference between 1.0 and the least representable value greater than 1.0". Given the inaccuracy of floating-point representation on computers, epsilon can only reliably be used to compare a constant 1.0 with a calculated value expected to be 1.0.
So, I don't see how changing the Epsilon constants will solve the issue you're describing.
sernamar
wayne-o
1.401298E-45
Double.Epsilon
4.94065645841247E-324
I'm not sure what my actual epsilon is but my computer spit that out when I was in immediate mode.
Todd Malone
Whether they're useful, and whether you use them properly are two different questions. Machine epsilon plays an important role in numerical analysis, and the relation between machine epsilon and the result of any mathematical operation are tightly constrained and guaranteeed by standard, and by the implementation of an x86 processor. Most undergraduate-level university CS courses would include (I would hope) a mandatory course in numerical analysis, in which machine Epsilon plays an important role..
The precise test you were after would have been:
if (Math.Abs(difference/84.33f) > 17*Float.ProperEpsilon/2) {
System.Diagnostics.Debug.Writeline("omg my floating point unit is broken").
}
(assuming that you don't want to drill down further into the implicit numeric error introduced when converting "84.33f" to an IEEE float).
> Given the inaccuracy of floating-point representation on computers, epsilon can
> only reliably be used to compare a constant 1.0 with a calculated value expected to be 1.0.
> Given the inaccuracy of floating-point representation on computers, epsilon can only reliably
> be used to compare a constant 1.0 with a calculated value expected to be 1.0.
Beg to differ. Errors introduced by floating point operations are well understood and are definitely tractable; but it does require significant insight into what was done, and what the precision guarantees of a particular operation are (said guarantees usually specified in terms of machine epsilon of the C++ standard, not minimum positive value of the CLR standard). Really. Honestly. There's a significant body of theory behind floating point operation, and a magnificent standard (the IEEE 754 standard) based on that significant body of theory, which provides the guarantees that allow us to predict the maximum error of a floating point operation.
And whether it's academic or not, I have a very precise non-academic need for the value of machine epsilon.