EMathError
Delphi Programming Language
Severity: ModerateWhat Does This Error Mean?
EMathError is the parent class for floating-point exceptions in Delphi. It covers errors like overflow (result too large), underflow (result too small), invalid operations (like dividing zero by zero), and division by zero in floating-point arithmetic. You will usually see a more specific sub-class: EOverflow, EUnderflow, EInvalidOp, or EZeroDivide.
Affected Models
- All Delphi versions
- RAD Studio
- Applications using floating-point arithmetic or the Math unit
Common Causes
- Floating-point division by zero — dividing a non-zero float by 0.0 (integer division by zero raises EDivByZero instead)
- A calculation resulting in a value larger than the maximum representable floating-point number (overflow)
- A floating-point operation on an invalid value — such as the square root of a negative number or log of zero
- Calling trigonometric or logarithmic functions from the Math unit with out-of-range arguments
- Importing a floating-point number from a string that contains an invalid value like NaN or Infinity when your FPU flags are set to raise exceptions for these
How to Fix It
-
Check which specific sub-class was raised. EOverflow means the result was too large. EUnderflow means too close to zero. EZeroDivide means floating-point division by zero. EInvalidOp means the operation itself was undefined (like Sqrt of a negative).
In your except block: on E: EZeroDivide do ... on E: EOverflow do ... on E: EMathError do ... — catch from most specific to most general.
-
Add validation before the operation. Check that divisors are non-zero before dividing. Check that values passed to Sqrt, Ln, ArcSin, and similar functions are within their valid range.
Sqrt requires x >= 0. Ln requires x > 0. ArcSin and ArcCos require -1 <= x <= 1. Check these before calling.
-
Use the IsNan() and IsInfinite() functions from the Math unit to check for problematic float values before using them in further calculations.
Example: if IsNaN(value) or IsInfinite(value) then raise Exception.Create('Invalid value encountered');
-
To allow floating-point operations to return NaN or Infinity silently (instead of raising exceptions), use Set8087CW or SetExceptionMask from the Math unit to disable specific FPU exception flags.
Example: SetExceptionMask(exAllArithmeticExceptions); — disables all FPU exceptions. Results become NaN or Infinity rather than raising EMathError. Use this when you want to check results after the fact rather than handling exceptions.
-
For financial calculations, avoid floats entirely. Use the Currency type for money — it is a fixed-point 64-bit type that does not have floating-point rounding or overflow issues. Use the Math unit's RoundTo function for controlled rounding.
Currency in Delphi stores values as integers scaled by 10,000. It never has the floating-point approximation problems that cause subtle bugs in financial software.
When to Call a Professional
EMathError and its sub-classes are always fixable in your own code. Check the specific sub-class to know exactly what went wrong, then add validation before the calculation. For financial or scientific applications, consider using extended precision types or the Decimal library.
Frequently Asked Questions
What is the difference between EZeroDivide and EDivByZero?
EZeroDivide is a sub-class of EMathError and is raised for floating-point division by zero (e.g., 1.0 / 0.0). EDivByZero is a sub-class of EIntError and is raised for integer division by zero (e.g., 1 div 0). They look similar but come from different exception hierarchies.
Why does my program sometimes get NaN instead of an exception?
Whether a floating-point error raises an exception or silently produces NaN/Infinity depends on the FPU control word settings. By default, Delphi raises exceptions for most FPU errors. But if your application initialises third-party libraries (especially those that call SetExceptionMask internally), the FPU mask may have been changed. Adding Set8087CW($1332) after library initialisation restores Delphi's default strict FPU settings.
How do I prevent EMathError from crashing my application in production?
Wrap floating-point operations in try/except blocks and handle EMathError (or specific sub-classes) gracefully. Log the error with the input values so you can diagnose it later. Return a safe default value (like 0 or a sentinel value) and continue processing. Also add input validation before calculations so bad values are caught before reaching the FPU.