#1,084 – Representing Numbers Using Scientific Notation

We often represent numbers (especially floating point numbers) using something called scientific notation.

With scientific notation (in base 10), you represent a number using the form:

1084-001

The a term is known as the significand, or mantissa and the b term is known as the exponent.

Scientific notation is useful because it allows easily writing very large or very small numbers by using the exponent to avoid writing a bunch of extra zeroes.

We also typically write the number so that the significand only has one significant digit, that is–one digit to the left of the decimal point.  (This is known as normalized form).

For example:

1084-002

Notice that we can now write very large and very small numbers fairly concisely:

1084-003

 

We only need to write down the numbers’ significant digits (i.e. significand), that is–the non-zero digits that contribute to the number’s precision.  (Zeroes between non-zeroed digits are also significant).

Advertisement

#416 – Use an Epsilon to Compare Two Floating Point Numbers

Because of problems with the precision of floating point numbers, two numbers that would ought to be considered equal might actually have different values.  Because of this, you typically don’t want to use the == operator on floating point numbers, when checking for equality.  Instead, you likely want to see if the difference between the two numbers is small enough that the numbers can be considered equal.

Here’s helper function that determines if two float values are nearly equal.

        public static bool NearlyEqual(float f1, float f2)
        {
            // Equal if they are within 0.00001 of each other
            return Math.Abs(f1 - f2) < 0.00001;
        }

We then get the following results:

            float f1 = 1.0f / 6.0f;
            float f2 = (f1 * 6.0f) - 1.0f;   // Should be 0.0
            float f3 = 0.0f;

            bool check = (f2 == f3);       // false !
            check = NearlyEqual(f2, f3);   // true


The value that you choose for epsilon will typically depend on your application.

#415 – Be Careful When Checking Floating Point Numbers for Equality

When you check two floating point numbers for equality in C#, you might sometimes be surprised at the result.

Consider the following example.  f2 is equal to six sixths (1.0), minus 1.0–which should be equal to 0.0.  But when we compare the result to 0.0, we see that the values are not equal.

            float f1 = 1.0f / 6.0f;
            float f2 = (f1 * 6.0f) - 1.0f;   // Should be 0.0
            float f3 = 0.0f;

            bool check = (f2 == f3);    // Should be true, but is false !

This happens because floating point numbers can’t necessarily be represented exactly when stored in a floating point variable.  Instead, the value stored can be very close, but not equal to, the desired value.

Here’s the output from the example above.  f2 should be equal to 0.0, after our calculation.  It is instead very nearly equal to 0.0.  Because of this, the comparison to the constant 0.0 fails.