Floating-point math often confuses programmers. I’m not going to try to clear up all the things that lead to confusion here; there isn’t enough space. I'm only going to talk about two terms, "exception" and "trap", that each mean two different things depending on whether you’re talking about C++ or about floating-point math. Keep the context in mind and you’re less likely to be confused.
Each of these contexts has its own fundamental document. For C++ it’s the C++ standard, formally known as ISO/IEC 14882:2003. That defines the syntax and semantics of the C++ programming language, and tells you what a program that meeets the syntactic and semantic requirements should do. Floating-point math also has a document, variously known as IEEE-754, IEC 559, and IEC 60559:1989. (There's a more recent version of this one that adds decimal floating-point math, but that doesn’t concern us now.) It prescribes the layout and properties of single- and double-precision floating-point types, and the properties, but not the layout, of higher precision versions of these two types. More important for our purposes now, it sets out what you can do with those types and what happens when an error occurs.
The C++ standard doesn’t say much about floating-point arithmetic, leaving it up to the implementation to document what it does. Many systems, including the ubiquitous PC, follow the IEEE-754 standard. So, even though the C++ standard doesn’t require it, we’ll look here at how errors are handled under IEEE-754.
In C++, when your code detects an error that can’t be fixed locally, it should throw an exception. Some function higher up in the call stack should catch that exception. If no function catches the exception, the program exits with a call to std::terminate()
.
According to IEEE-754, when something unusual occurs in floating-point math, such as dividing 0.0
by 0.0
or dividing 1.0
by 0.0
, an exception occurs. This is not a C++ exception; it’s a floating-point exception. The default behavior of floating-point exceptions is benign: 0.0/0.0
becomes a NaN
(Not A Number) value, and 1.0/0.0
becomes an infinity
value.
Under IEEE-754, your program can change the behavior of a floating-point exception by installing a "trap handler". Standard C and Standard C++ do not support trap handlers. You’ll have to check your compiler’s documentation if you want to do this.
A trap handler is a function that will be called when a floating-point exception occurs. It should set or clear the appropriate floating-point status flags, and return a value that will be used as the result of the invalid operation.
For example, if your program has installed a trap handler for the invalid operation exception, whenever your code tries to do an invalid floating-point operation such as dividing 0.0
by 0.0
your trap handler will be called. To imitate the default behavior for this exception, your trap handler would set the invalid operation flag and return a NaN value.
A trap representation, on the other hand, is entirely different. Under the C99 standard, it refers to a value that results in undefined behavior if you try to use it. Undefined behavior means that the C++ standard doesn’t tell you what happens. Some hardware systems will do nasty things with variables that hold trap representations, on the theory that detecting bad values is good for you.
So the next time you’re confused about floating-point errors, remember that a floating-point exception is not a C++ exception, and that a trap handler has nothing to do with a trap representation.
Pete Becker
July 29, 2008
To see earlier articles from Bits and Pieces, click here.
I’m available for consulting on most aspects of C and C++ software development, with particular emphasis on assisting in the following areas:
I’ve been a professional programmer and development manager for over twenty years. During that time, I’ve written test code for C and C++ compilers and libraries, implemented parts of the standard C++ library and most of the TR1 library, and managed testing and development of tools and utilities for C and C++ programmers. I’ve also written extensively about C and C++, in columns for The C++ Report, The C/C++ Users Journal, and Doctor Dobbs Journal, and most recently, in a book, The C++ Standard Library Extensions: A Tutorial and Reference. I’ve been on the C++ standards committee since its inception, back in 1989, and I’ve been the committee’s Project Editor for the C++ standard since 2004.
Copyright © 2008 by Roundhouse Consulting, Ltd. All rights reserved.