## digitalmars.D - weird behavior for machine epsilon in float, double and real

- Andrew Spott <andrew.spott gmail.com> Apr 10 2009
- bearophile <bearophileHUGS lycos.com> Apr 11 2009
- BCS <none anon.com> Apr 11 2009
- Walter Bright <newshound1 digitalmars.com> Apr 11 2009

So, for the following code, I get something I think is a little off. I get the same value for all three variable types. I'm kind of new to this, but I would think that a 32 bit would give me a different "smallest value" than a 64 bit or 80 bit (if real even evaluates to 80 bit on my machine). What am I doing wrong, or is this a bug? import std.stdio; void main() { //Find Machine Epsilon: double ep = 1.0; double n = 1.0; while (ep + n != n) { ep = ep / 2; } writefln(ep); real epr = 1.0; real nr = 1.0; while (epr + nr != nr) epr = epr / 2; writefln(epr); float epf = 1.0; float nf = 1.0; while (epf + nf != nf) epf = epf / 2; writefln(epr); }

Apr 10 2009

Andrew Spott:import std.stdio; [...]

This is the same code of yours, a bit refactored: import std.stdio: writefln; template Tuple(T...) { alias T Tuple; } void computeEpsilon(T)() { T ep = 1; T n = 1; while ((ep + n) != n) ep /= 2; writefln("%.30f type: %s", ep, typeid(T)); } void main() { foreach (T; Tuple!(float, double, real)) computeEpsilon!(T)(); } Bye, bearophile

Apr 11 2009

Hello Andrew,So, for the following code, I get something I think is a little off. I get the same value for all three variable types. I'm kind of new to this, but I would think that a 32 bit would give me a different "smallest value" than a 64 bit or 80 bit (if real even evaluates to 80 bit on my machine). What am I doing wrong, or is this a bug?

This is a classic case of the optimizer getting in your way by doing all the math in the FPU (the other classic cases is it noting that as long as ep!=0, ep+n "can't" equal n). If you are on x86 than the only type the FPU uses inside is 80bit-real.import std.stdio; void main() { //Find Machine Epsilon: double ep = 1.0; double n = 1.0; while (ep + n != n) { ep = ep / 2; } writefln(ep); real epr = 1.0; real nr = 1.0; while (epr + nr != nr) epr = epr / 2; writefln(epr); float epf = 1.0; float nf = 1.0; while (epf + nf != nf) epf = epf / 2; writefln(epr); }

Apr 11 2009

Andrew Spott wrote:So, for the following code, I get something I think is a little off. I get the same value for all three variable types. I'm kind of new to this, but I would think that a 32 bit would give me a different "smallest value" than a 64 bit or 80 bit (if real even evaluates to 80 bit on my machine). What am I doing wrong, or is this a bug?

The expression: (ep + n != n) is evaluated at 80 bit precision, regardless of the size of its operands. The idea is that the floating point sizes only specify a minimum precision, and the compiler (where it makes sense) can use a larger precision to do constant folding and/or for intermediate values. If you need the epsilon values, use float.epsilon, double.epsilon, and real.epsilon.

Apr 11 2009