3

So small question, I've been looking into moving part of my C# code to C++ for performance reasons. Now when I look at my float.Epsilon in C# its value is different from my C++ value.

In C# the value, as described by microsoft is 1.401298E-45.

In C++ the value, as described by cppreferences is 1.19209e-07;

How can it be that the smallest possible value for a float/single can be different between these languages?

If I'm correct, the binary values should be equal in terms of number of bytes an maybe even their binary values. Or am I looking at this the wrong way?

Hope someone can help me, thanks!

Foitn
  • 604
  • 6
  • 25
  • 1
    The definitions of epsilon are different. In C# ist is the difference between 0 and the next value an in C++ it is the difference between 1 and the next value. – gerum Aug 13 '21 at 10:02
  • That Microsoft page is rife with bad statements about floating-point. Avoid using the information in it. Some problems: (a) “zero and half the value of Epsilon are considered to be equal”: You cannot have half the value of Epsilon in a `Float`; it is not representable. (b) “format consists of a sign, a 23-bit mantissa or significand…”: The significand is 24 bits, although stored as 23 bits in one field and 1 bit depending on the exponent field. – Eric Postpischil Aug 13 '21 at 10:51
  • (c) “machine epsilon, which represents the upper bound of the relative error due to rounding…”: It can be a gauge of the error in a single operation, not quite right to say it represents the upper bound or that it is for the relative error. With round-to-nearest, the actual upper bound is ½ an ULP, and the true relative error is a bit complicated, as it varies across a binade. – Eric Postpischil Aug 13 '21 at 10:59
  • (d) “the constant on the right side is precise only to the specified digits”: Both values have the same precision; the one on the right is inaccurate for ⅓. Microsoft’s statements about precision are [bad](https://stackoverflow.com/a/61614323/298225). – Eric Postpischil Aug 13 '21 at 10:59
  • (e) “If you create a custom algorithm that determines whether two floating-point numbers can be considered equal, you must use a value that is greater than the Epsilon constant to establish the acceptable absolute margin of difference for the two values to be considered equal.”: [There is no general solution for comparing floating-point numbers](https://stackoverflow.com/a/21261885/298225); every application must deal with both false positives and false negatives, which may be particular to its situation. So it is not true that “you must use a value that is greater than the Epsilon constant.” – Eric Postpischil Aug 13 '21 at 11:02
  • (f) “On ARM systems, the value of the Epsilon constant is too small to be detected, so it equates to zero.”: I suspect they are trying to say the flush-to-zero behavior for denormals interferes with using the Epislon constant. – Eric Postpischil Aug 13 '21 at 11:04

3 Answers3

4

The second value you quoted is the machine epsilon for IEEE binary32 values.

The first value you quoted is NOT the machine epsilon. From the documentation you linked:

The value of the Epsilon property is not equivalent to machine epsilon, which represents the upper bound of the relative error due to rounding in floating-point arithmetic.

From the wiki Variant Definitions section for machine epsilon:

The IEEE standard does not define the terms machine epsilon and unit roundoff, so differing definitions of these terms are in use, which can cause some confusion.

...

The following different definition is much more widespread outside academia: Machine epsilon is defined as the difference between 1 and the next larger floating point number.

The C# documentation is using that variant definition.

So the answer is that you are comparing two different types of Epsilon.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
2

C++

Returns the machine epsilon, that is, the difference between 1.0 and the next value representable by the floating-point type T. https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon

C#

Represents the smallest positive Single value that is greater than zero. This field is constant. https://learn.microsoft.com/en-us/dotnet/api/system.single.epsilon?view=net-5.0

Conclusion

C# has next value from 0, C++ has next from 1. Two completely different things.

Edit: The other answer is probably more correct

DownloadPizza
  • 3,307
  • 1
  • 12
  • 27
0

From the link you referenced, you should use the value FLT_TRUE_MIN ("minimum positive value of float") if you want something similar to .NET Single.Epsilon ("smallest positive single value that is greater than zero").

Dave Doknjas
  • 6,394
  • 1
  • 15
  • 28