digitalmars.D - weird behavior for machine epsilon in float, double and real
- Andrew Spott (23/23) Apr 10 2009 So, for the following code, I get something I think is a little off. I ...
- bearophile (17/19) Apr 11 2009 This is the same code of yours, a bit refactored:
- BCS (5/38) Apr 11 2009 This is a classic case of the optimizer getting in your way by doing all...
- Walter Bright (8/15) Apr 11 2009 The expression: (ep + n != n) is evaluated at 80 bit precision,
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