-1

Consider the following:

#include <iostream>
//#include <math.h>
#include <cmath>
using namespace std;

int main(int argc, char **argv)
{
    double ldexp_signif = 0.545528;
    double ldexp_expo = 12;
    double ldexp_output = 0;

    double frexp_input = 2234.484565523;
    double frexp_signif = 0;
    int frexp_expo = 0;

    int n;

    // create float from sig and expo
    ldexp_output = ldexp (ldexp_signif , ldexp_expo);
    printf ("The significand INPUT is %f\n",ldexp_signif);
    printf ("The exponent INPUT is %f\n",ldexp_expo);
    printf ("The float OUTPUT is %f\n\n",ldexp_output);

    // get sig and expo from float
    frexp_signif = frexp (frexp_input , &frexp_expo);
    printf ("The float INPUT is %f\n",frexp_input);
    printf ("the exponent OUTPUT is %i\n",frexp_expo);
    printf ("The significand OUTPUT is %f\n",frexp_signif);

    // ==================================
    cout << endl << "=======================================" << endl << "Program completed and terminated successfully." << endl << "Press enter to exit";
    cin.ignore();
    return 0;
}

The output is:

The significand INPUT is 0.545528
The exponent INPUT is 12.000000
The float OUTPUT is 2234.482688

The float INPUT is 2234.484566
the exponent OUTPUT is 12
The significand OUTPUT is 0.545528

=======================================
Program completed and terminated successfully.
Press enter to exit

What I would like to know is why ldexp gives a float output different from the float input of frexp when ldexp is given the same significand and exponent generated by frexp? I found this article but that article didn't answer my question. I saw this also, it states that floating point calculations are not exact. The output to console is only for demonstration purposes, the significand and exponent are to be read from a game data file that was written using Single-precision floating-point format then used to display that data, it is not going to be used for anything potentially life-threating like medical or military applications, should I just take it for what it is or look for a more accurate solution?

1 Answers1

4

The following assumes IEEE 754 is in use with its basic 64-bit binary floating-point format.

The source text double frexp_input = 2234.484565523; initializes frexp_input to 2234.484565523000128450803458690643310546875.

Then frexp sets the exponent to 12 and returns 0.545528458379638703235059438156895339488983154296875.

Printing that value with %f displays “0.545528”, which is a decimal numeral for a different number, since the actual value, 0.545528458379638703235059438156895339488983154296875, was rounded for display.

When that number, .545528, is used in the source text double ldexp_signif = 0.545528;, it initializes ldexp_signif to 0.54552800000000001290345608140341937541961669921875.

When that is multiplied by 212 using ldexp, the result is 2234.48268800000005285255610942840576171875.

Printing that value with %f displays “2234.482688”, again because the number was rounded for display.

Summary: ldexp was not given the significand generated by frexp. The significand generated by frexp was 0.545528458379638703235059438156895339488983154296875, but the significand given to ldexp was 0.54552800000000001290345608140341937541961669921875. These are different, so a different result was obtained.

Observe that the significand was changed around its seventh significant digit, and the scaled values changed around their seventh significant digits.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312