converting float to double

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dilip

    converting float to double


    Recently in our code, I ran into a situation where were stuffing a
    float inside a double. The precision was extended automatically
    because of that. To make a long story short, this caused problems
    elsewhere in another part of the system where that figure was used for
    some calculation and some eventual truncation led to the system going
    haywire. So my question is, given this code:

    int main()
    {
    float f = 59.89F;
    /* the following line caused problems */
    double d = f;

    /* they ended up solving it like this */
    f *= 1000.0;
    double dd = (double)f / 1000.0;

    return 0;
    }

    I see what is being done but why does the latter make the situation
    better?
    (consider 'f' in real life to hold stock prices)

  • mark_bluemel@pobox.com

    #2
    Re: converting float to double


    Dilip wrote:
    Recently in our code, I ran into a situation where were stuffing a
    float inside a double. The precision was extended automatically
    because of that. To make a long story short, this caused problems
    elsewhere in another part of the system where that figure was used for
    some calculation and some eventual truncation led to the system going
    haywire. So my question is, given this code:
    >
    int main()
    {
    float f = 59.89F;
    /* the following line caused problems */
    double d = f;
    >
    /* they ended up solving it like this */
    f *= 1000.0;
    double dd = (double)f / 1000.0;
    >
    return 0;
    }
    >
    I see what is being done but why does the latter make the situation
    better?
    (consider 'f' in real life to hold stock prices)
    Not a good idea...

    Floating point is by its nature imprecise - multiplying by 1000 simply
    adjusts the imprecision in a way which was helpful in this specific
    case, but may not be helpful in all cases (AFAIK).

    If you want to safely and accurately handle this sort of data, sources
    such as http://www2.hursley.ibm.com/decimal/ may be helpful.

    Comment

    • CBFalconer

      #3
      Re: converting float to double

      Dilip wrote:
      >
      Recently in our code, I ran into a situation where were stuffing a
      float inside a double. The precision was extended automatically
      because of that. To make a long story short, this caused problems
      elsewhere in another part of the system where that figure was used
      for some calculation and some eventual truncation led to the system
      going haywire. So my question is, given this code:
      >
      int main()
      {
      float f = 59.89F;
      /* the following line caused problems */
      double d = f;
      >
      /* they ended up solving it like this */
      f *= 1000.0;
      double dd = (double)f / 1000.0;
      >
      return 0;
      }
      >
      I see what is being done but why does the latter make the
      situation better?
      (consider 'f' in real life to hold stock prices)
      It doesn't. It should make it dead wrong. Either you are not
      showing the real situation or you have a compiler bug.

      Alternatively, if you are depending on exact values from floats
      and/or doubles, your code is broken. Since stock prices (today)
      are decimalized, just use a normalized integer of suitable size.
      Read Knuth (TAOCP) on floating point and expected errors.

      --
      Chuck F (cbfalconer at maineline dot net)
      Available for consulting/temporary embedded and systems.
      <http://cbfalconer.home .att.net>


      Comment

      • pete

        #4
        Re: converting float to double

        Dilip wrote:
        >
        Recently in our code, I ran into a situation where were stuffing a
        float inside a double. The precision was extended automatically
        because of that. To make a long story short, this caused problems
        elsewhere in another part of the system where that figure was used for
        some calculation and some eventual truncation led to the system going
        haywire. So my question is, given this code:
        >
        int main()
        {
        float f = 59.89F;
        /* the following line caused problems */
        double d = f;
        >
        /* they ended up solving it like this */
        f *= 1000.0;
        double dd = (double)f / 1000.0;
        >
        return 0;
        }
        >
        I see what is being done but why does the latter make the situation
        better?
        (consider 'f' in real life to hold stock prices)
        I wouldn't have used a float variable like that to begin with.

        Use float,
        when you need the smallest floating point type.

        Use long double,
        when you need the floating point type
        with most precision and or range.

        Use double,
        all the rest of the time.

        --
        pete

        Comment

        • Dilip

          #5
          Re: converting float to double

          CBFalconer wrote:
          Dilip wrote:

          Recently in our code, I ran into a situation where were stuffing a
          float inside a double. The precision was extended automatically
          because of that. To make a long story short, this caused problems
          elsewhere in another part of the system where that figure was used
          for some calculation and some eventual truncation led to the system
          going haywire. So my question is, given this code:

          int main()
          {
          float f = 59.89F;
          /* the following line caused problems */
          double d = f;

          /* they ended up solving it like this */
          f *= 1000.0;
          double dd = (double)f / 1000.0;

          return 0;
          }

          I see what is being done but why does the latter make the
          situation better?
          (consider 'f' in real life to hold stock prices)
          >
          It doesn't. It should make it dead wrong. Either you are not
          showing the real situation or you have a compiler bug.
          I am showing exactly what is being done in our codebase. Why do you
          say there is a compiler bug? If you try the example, as soon as the
          1st line is executed the variable f contains 59.889999. After its
          stuffed into double d, it becomes 59.889999389648 437 (I know these
          values vary after a certain decimal position). The
          multiplication/division to 1000.0 however produces 59.890000000000 001
          in dd. The management somehow feels thats a more "accurate"
          representation. I guess after rounding off to 2 decimal places they
          expected 59.89 but a bug somewhere in the code ensured that the former
          case got rounded off to 59.88. It was off by a penny and that
          triggered major problems in other calculations.
          Since stock prices (today)
          are decimalized, just use a normalized integer of suitable size.
          Read Knuth (TAOCP) on floating point and expected errors.
          I am not exactly unfamiliar with floating point representations and its
          associated accuracy related problems but I think this is the first time
          I am working in a domain where such problems crop up on a more frequent
          basis. Could you please elaborate on that "normalized integer of
          suitable size"?

          Comment

          • Keith Thompson

            #6
            Re: converting float to double

            CBFalconer <cbfalconer@yah oo.comwrites:
            Dilip wrote:
            >Recently in our code, I ran into a situation where were stuffing a
            >float inside a double. The precision was extended automatically
            >because of that. To make a long story short, this caused problems
            >elsewhere in another part of the system where that figure was used
            >for some calculation and some eventual truncation led to the system
            >going haywire. So my question is, given this code:
            >>
            >int main()
            >{
            > float f = 59.89F;
            > /* the following line caused problems */
            > double d = f;
            >>
            > /* they ended up solving it like this */
            > f *= 1000.0;
            > double dd = (double)f / 1000.0;
            >>
            > return 0;
            >}
            >>
            >I see what is being done but why does the latter make the
            >situation better?
            >(consider 'f' in real life to hold stock prices)
            >
            It doesn't. It should make it dead wrong. Either you are not
            showing the real situation or you have a compiler bug.
            Are you sure about that? The code multiplies f by 1000.0, then
            divides the result by 1000.0. The *mathematical* result is the same,
            but the way it's done is likely to change the rounding behavior
            slightly. It's not likely to be a general solution to any problem.
            It smacks of "cargo cult programming"; see
            <http://www.catb.org/~esr/jargon/html/C/cargo-cult-programming.htm l>.
            Alternatively, if you are depending on exact values from floats
            and/or doubles, your code is broken. Since stock prices (today)
            are decimalized, just use a normalized integer of suitable size.
            Read Knuth (TAOCP) on floating point and expected errors.
            Another good resource is Goldberg's paper "What Every Computer
            Scientist Should Know About Floating-Point". Google "goldberg
            floating" to find it.

            --
            Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
            San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
            We must do something. This is something. Therefore, we must do this.

            Comment

            • William Hughes

              #7
              Re: converting float to double


              pete wrote:
              Dilip wrote:

              Recently in our code, I ran into a situation where were stuffing a
              float inside a double. The precision was extended automatically
              because of that. To make a long story short, this caused problems
              elsewhere in another part of the system where that figure was used for
              some calculation and some eventual truncation led to the system going
              haywire. So my question is, given this code:

              int main()
              {
              float f = 59.89F;
              /* the following line caused problems */
              double d = f;

              /* they ended up solving it like this */
              f *= 1000.0;
              double dd = (double)f / 1000.0;

              return 0;
              }

              I see what is being done but why does the latter make the situation
              better?
              (consider 'f' in real life to hold stock prices)
              >
              I wouldn't have used a float variable like that to begin with.
              >
              Use float,
              when you need the smallest floating point type.
              >
              Use long double,
              when you need the floating point type
              with most precision and or range.
              >
              Use double,
              all the rest of the time.
              >
              This comes squarely under the heading "If you can understand this
              advice you don't need it".

              - William Hughes
              --
              pete

              Comment

              • Random832

                #8
                Re: converting float to double

                2006-12-19 <4588563B.59D4@ mindspring.com> ,
                pete wrote:
                Dilip wrote:
                >>
                >Recently in our code, I ran into a situation where were stuffing a
                >float inside a double. The precision was extended automatically
                >because of that. To make a long story short, this caused problems
                >elsewhere in another part of the system where that figure was used for
                >some calculation and some eventual truncation led to the system going
                >haywire. So my question is, given this code:
                >>
                >int main()
                >{
                > float f = 59.89F;
                > /* the following line caused problems */
                > double d = f;
                >>
                > /* they ended up solving it like this */
                > f *= 1000.0;
                > double dd = (double)f / 1000.0;
                >>
                > return 0;
                >}
                >>
                >I see what is being done but why does the latter make the situation
                >better?
                >(consider 'f' in real life to hold stock prices)
                >
                I wouldn't have used a float variable like that to begin with.
                >
                Use float,
                when you need the smallest floating point type.
                >
                Use long double,
                when you need the floating point type
                with most precision and or range.
                Use integers,
                when you need to be exact to within a known specific unit, such as
                a dollar, cent, or Nth part of either.
                Use double,
                all the rest of the time.

                Comment

                • Random832

                  #9
                  Re: converting float to double

                  2006-12-19 <1166563496.656 669.292300@79g2 000cws.googlegr oups.com>,
                  Dilip wrote:
                  I am not exactly unfamiliar with floating point representations and its
                  associated accuracy related problems but I think this is the first time
                  I am working in a domain where such problems crop up on a more frequent
                  basis. Could you please elaborate on that "normalized integer of
                  suitable size"?
                  Have an integer variable [probably type long or long long] counting the
                  number of cents (or thousandths of a dollar, or whatever). Doing your
                  weird cast thing fixed the error in that one particular case, but could
                  have introduced other errors elsewhere.

                  Comment

                  • Dilip

                    #10
                    Re: converting float to double

                    Keith Thompson wrote:
                    CBFalconer <cbfalconer@yah oo.comwrites:
                    Dilip wrote:
                    Recently in our code, I ran into a situation where were stuffing a
                    float inside a double. The precision was extended automatically
                    because of that. To make a long story short, this caused problems
                    elsewhere in another part of the system where that figure was used
                    for some calculation and some eventual truncation led to the system
                    going haywire. So my question is, given this code:
                    >
                    int main()
                    {
                    float f = 59.89F;
                    /* the following line caused problems */
                    double d = f;
                    >
                    /* they ended up solving it like this */
                    f *= 1000.0;
                    double dd = (double)f / 1000.0;
                    >
                    return 0;
                    }
                    >
                    I see what is being done but why does the latter make the
                    situation better?
                    (consider 'f' in real life to hold stock prices)
                    It doesn't. It should make it dead wrong. Either you are not
                    showing the real situation or you have a compiler bug.
                    >
                    Are you sure about that? The code multiplies f by 1000.0, then
                    divides the result by 1000.0. The *mathematical* result is the same,
                    but the way it's done is likely to change the rounding behavior
                    slightly. It's not likely to be a general solution to any problem.
                    It smacks of "cargo cult programming"; see
                    <http://www.catb.org/~esr/jargon/html/C/cargo-cult-programming.htm l>.
                    I totally agree which is the reason why I posted to this NG to
                    understand what exactly is being solved by that 1000.0 workaround.
                    Another good resource is Goldberg's paper "What Every Computer
                    Scientist Should Know About Floating-Point". Google "goldberg
                    floating" to find it.
                    I came across that paper quite a few times in the past. I never
                    realized one day I would need to know that amount of detail. Do you
                    have any insights into that normalized integer thing everyone has been
                    pointing out so far? If one of you can give me an example, i'd
                    appreciate it.

                    Comment

                    • dcorbit@connx.com

                      #11
                      Re: converting float to double

                      Dilip wrote:
                      I came across that paper quite a few times in the past. I never
                      realized one day I would need to know that amount of detail. Do you
                      have any insights into that normalized integer thing everyone has been
                      pointing out so far? If one of you can give me an example, i'd
                      appreciate it.
                      Store the amount as pennies in a long long integer. The Goldberg paper
                      is a must read if you are doing numerics with other people's money.
                      IMO-YMMV.

                      #include <stdio.h>
                      #include <stdlib.h>

                      char string[256];
                      int main(void)
                      {
                      long long pennies;

                      try_again:
                      puts("Enter a cost in pennies:");
                      if (fgets(string, sizeof string, stdin)) {
                      sscanf(string, "%lld", &pennies);
                      printf("That's %lld dollars and %lld cents or $%lld.%lld\n",
                      pennies / 100, pennies % 100, pennies / 100, pennies % 100);
                      } else
                      goto try_again;

                      return EXIT_SUCCESS;
                      }
                      /* e.g.:
                      Enter a cost in pennies:
                      99999999
                      That's 999999 dollars and 99 cents or $999999.99
                      */

                      Comment

                      • Malcolm

                        #12
                        Re: converting float to double




                        "Dilip" <rdilipk@lycos. comwrote in message
                        news:1166540869 .319736.190700@ 79g2000cws.goog legroups.com...
                        >
                        Recently in our code, I ran into a situation where were stuffing a
                        float inside a double. The precision was extended automatically
                        because of that. To make a long story short, this caused problems
                        elsewhere in another part of the system where that figure was used for
                        some calculation and some eventual truncation led to the system going
                        haywire. So my question is, given this code:
                        >
                        int main()
                        {
                        float f = 59.89F;
                        /* the following line caused problems */
                        double d = f;
                        >
                        /* they ended up solving it like this */
                        f *= 1000.0;
                        double dd = (double)f / 1000.0;
                        >
                        return 0;
                        }
                        >
                        I see what is being done but why does the latter make the situation
                        better?
                        (consider 'f' in real life to hold stock prices)
                        >
                        That is called hacking.
                        Somehow a cent must have been knocked off in the code - decimals cannot be
                        represented perfectly in binary floating point notation - leading the
                        program to suspect salami tactics. Multiplying by 1000 converts the number
                        to an integer, and the division is done in double precision, so the cent
                        might not have been dropped.

                        This approach to problem solving, incidentally, is known as hacking, and is
                        an indication that the company's management is in a serious mess.
                        --

                        freeware games to download.



                        Comment

                        • CBFalconer

                          #13
                          Re: converting float to double

                          Dilip wrote:
                          Keith Thompson wrote:
                          >CBFalconer <cbfalconer@yah oo.comwrites:
                          >>Dilip wrote:
                          >>>
                          >>>Recently in our code, I ran into a situation where were stuffing a
                          >>>float inside a double. The precision was extended automatically
                          >>>because of that. To make a long story short, this caused problems
                          >>>elsewhere in another part of the system where that figure was used
                          >>>for some calculation and some eventual truncation led to the system
                          >>>going haywire. So my question is, given this code:
                          >>>>
                          >>>int main()
                          >>>{
                          >>> float f = 59.89F;
                          >>> /* the following line caused problems */
                          >>> double d = f;
                          >>>>
                          >>> /* they ended up solving it like this */
                          >>> f *= 1000.0;
                          >>> double dd = (double)f / 1000.0;
                          >>>>
                          >>> return 0;
                          >>>}
                          >>>>
                          >>>I see what is being done but why does the latter make the
                          >>>situation better?
                          >>>(consider 'f' in real life to hold stock prices)
                          >>>
                          >>It doesn't. It should make it dead wrong. Either you are not
                          >>showing the real situation or you have a compiler bug.
                          >>
                          >Are you sure about that? The code multiplies f by 1000.0, then
                          >divides the result by 1000.0. The *mathematical* result is the same,
                          >but the way it's done is likely to change the rounding behavior
                          >slightly. It's not likely to be a general solution to any problem.
                          >It smacks of "cargo cult programming"; see
                          ><http://www.catb.org/~esr/jargon/html/C/cargo-cult-programming.htm l>.
                          >
                          I totally agree which is the reason why I posted to this NG to
                          understand what exactly is being solved by that 1000.0 workaround.
                          >
                          >Another good resource is Goldberg's paper "What Every Computer
                          >Scientist Should Know About Floating-Point". Google "goldberg
                          >floating" to find it.
                          >
                          I came across that paper quite a few times in the past. I never
                          realized one day I would need to know that amount of detail. Do you
                          have any insights into that normalized integer thing everyone has been
                          pointing out so far? If one of you can give me an example, i'd
                          appreciate it.
                          As a temporary measure, try converting the value to a long:

                          long longvalueincent s;

                          longvalueincent s = (f * 100) + 0.5; /* control rounding */

                          and, to print it out, try:

                          printf("%ld.%ld ", longvalueincent s/100, longvalueincent s%100);
                          fflush(stdout);

                          Note that you don't need any casts. A cast is probably an error.

                          You can probably incorporate all this in a single function that
                          dumps the double rounded to two decimals, but reading the printf
                          documentation is likely to be more rewarding.

                          You could also hire me. :-) See below.

                          --
                          Chuck F (cbfalconer at maineline dot net)
                          Available for consulting/temporary embedded and systems.
                          <http://cbfalconer.home .att.net>


                          Comment

                          • Malcolm

                            #14
                            Re: converting float to double




                            <dcorbit@connx. comwrote in message
                            news:1166567641 .034215.323880@ t46g2000cwa.goo glegroups.com.. .
                            Dilip wrote:
                            >I came across that paper quite a few times in the past. I never
                            >realized one day I would need to know that amount of detail. Do you
                            >have any insights into that normalized integer thing everyone has been
                            >pointing out so far? If one of you can give me an example, i'd
                            >appreciate it.
                            >
                            Store the amount as pennies in a long long integer. The Goldberg paper
                            is a must read if you are doing numerics with other people's money.
                            IMO-YMMV.
                            >
                            Or in a double, but as an integral number of pence.
                            That way the maths is accurate up to 48 bits or so, and degrades garcefully
                            under hyperinflation.
                            --

                            freeware games to download.



                            Comment

                            • William Hughes

                              #15
                              Re: converting float to double


                              Dilip wrote:
                              Recently in our code, I ran into a situation where were stuffing a
                              float inside a double. The precision was extended automatically
                              because of that. To make a long story short, this caused problems
                              elsewhere in another part of the system where that figure was used for
                              some calculation and some eventual truncation led to the system going
                              haywire. So my question is, given this code:
                              >
                              int main()
                              {
                              float f = 59.89F;
                              /* the following line caused problems */
                              double d = f;
                              >
                              /* they ended up solving it like this */
                              f *= 1000.0;
                              double dd = (double)f / 1000.0;
                              >
                              return 0;
                              }
                              >
                              I see what is being done but why does the latter make the situation
                              better?
                              (consider 'f' in real life to hold stock prices)
                              For the purposes of this explanation treat double as exact
                              and float as approximate.

                              The problem is that most exact decimal fractions cannot
                              be represented exactly by floats. So you need to use
                              a value that is just a little above or just a little below.

                              Suppose we have

                              f=0.0001

                              then f will have a value slightly below 0.0001
                              (or maybe not, but it did on my machine just now).

                              Now multiply by 1000
                              Now f will have to approximate 0.1. The best approximation is
                              a value slightly above 0.1 (at least on my machine just now)
                              So after

                              1000*f

                              we get a value slightly above 0.1. We now assign to a double

                              dd=1000*f

                              (This is done by first calculating 1000*f as a float and then
                              assigning to double). We next divide dd by 1000.
                              dd now has a value slightly greater than 0.0001.

                              So the net effect of multiplying by 1000, storing in a double, then
                              dividing by 1000, is to convert a value slightly below 0.0001 to a
                              value
                              slightly above 0.0001. Because the code is clearly incompetently
                              written, it will later blindly truncate, converting a miniscule
                              difference into
                              a noticable one.

                              Of course if you start out with some other value for f, something
                              different
                              may happen. Something different may happen on different machines,
                              or with different compilers, or with different compiler options, or on
                              different days, or on different runs, or at different times within the
                              same run.

                              I wouldn't trust this code in a rigged demo.

                              - William Hughes.

                              Comment

                              Working...