www.digitalmars.com         C & C++   DMDScript  

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

reply Andrew Spott <andrew.spott gmail.com> writes:
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
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent BCS <none anon.com> writes:
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
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
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