digitalmars.D - Division by zero - why no exception?
- A Bothe (7/7) Jan 10 2010 Hey everyone,
- bearophile (61/65) Jan 10 2010 To me this code prints "nan" (I am using the latest D2 compiler, but D1 ...
- bearophile (25/26) Jan 10 2010 That was not precise, the FPC struct is restored at the end of the main(...
- A Bothe (1/1) Jan 10 2010 OK, thanks!
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
A Bothe:double a=0.0; double f=1/a; writeln(f); ... prints 2.66825e-284To 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
(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