www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Division by zero - why no exception?

reply A Bothe <info alexanderbothe.com> writes:
Hey everyone,
I noticed something:

double a=0.0;
double f=1/a;
writeln(f);

... prints 2.66825e-284

normally it shall throw a exception or do something else ... but it doesn't ...
why?
Jan 10 2010
parent reply bearophile < bearophileHUGS lycos.com> writes:
A Bothe:
 double a=0.0;
 double f=1/a;
 writeln(f);
 ... prints 2.66825e-284
To me this code prints "nan" (I am using the latest D2 compiler, but D1 too prints nan): import std.stdio: writeln; void main() { double a = 0.0; double f = 1 / a; writeln(f); } If you want the division by zero error you have to activate it (but be careful, this works only in the main(), probably to keep tidy the semantics of pure functions): import std.stdio: writeln; import std.math: FloatingPointControl; void main() { FloatingPointControl fpc; fpc.enableExceptions(FloatingPointControl.severeExceptions); double a = 0.0; double f = 1 / a; writeln(f); } Prints at run time: object.Error: Float Divide by Zero But be careful, that works at run time only, so if you use compile time constants: import std.stdio: writeln; import std.math: FloatingPointControl; void main() { FloatingPointControl fpc; fpc.enableExceptions(FloatingPointControl.severeExceptions); enum double a = 0.0; enum double f = 1 / a; writeln(f); } It prints nan again. Eventually the behaviour of D floating point operations at compile time will need to become much more similar to their run-time behaviour, to simplify language semantics and to have more "deterministic" results. You can see a similar problem here, some floating point circus, that I've recently shown in D.learn: import std.math: sqrt, PI; import std.stdio: writefln; void main() { const double x1 = 3.0 * PI / 16.0; writefln("%.17f", sqrt(1.0 / x1)); double x2 = 3.0 * PI / 16.0; writefln("%.17f", sqrt(1.0 / x2)); real x3 = 3.0 * PI / 16.0; writefln("%.17f", sqrt(1.0 / x3)); real x4 = 3.0L * PI / 16.0L; writefln("%.17f", sqrt(1.0L / x4)); } Output with various D compilers: DMD1: 1.30294003174111994 1.30294003174111972 1.30294003174111979 1.30294003174111979 DMD2: 1.30294003174111972 1.30294003174111972 1.30294003174111979 1.30294003174111979 LDC: 1.30294003174111994 1.30294003174111994 1.30294003174111972 1.30294003174111972 Bye, bearophile
Jan 10 2010
parent reply bearophile <bearophileHUGS lycos.com> writes:
 (but be careful, this works only in the main(), probably to keep tidy the
semantics of pure functions):
That was not precise, the FPC struct is restored at the end of the main() scope, so if you call a function inside main it will keep the same FPC struct, and this raises the division by zero error: import std.stdio: writeln; import std.math: FloatingPointControl; void foo() { double a = 0.0; double f = 1 / a; writeln(f); } void main() { FloatingPointControl fpc; fpc.enableExceptions(FloatingPointControl.severeExceptions); foo(); } Also, you can't catch it: void foo() { double f = 0; try { double a = 0.0; f = 1 / a; // object.Error: Float Divide by Zero } catch (Error e) { } writeln(f); } Bye, bearophile
Jan 10 2010
parent A Bothe <info alexanderbothe.com> writes:
OK, thanks!
Jan 10 2010