converting float to double

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

    #16
    Re: converting float to double

    dcorbit@connx.c om wrote:
    printf("That's %lld dollars and %lld cents or $%lld.%lld\n",
    pennies / 100, pennies % 100, pennies / 100, pennies % 100);
    printf("That's %lld dollars and %lld cents or $%lld.%02lld\n" ,
    pennies / 100, pennies % 100, pennies / 100, pennies % 100);


    --
    Thad

    Comment

    • Dik T. Winter

      #17
      Re: converting float to double

      In article <1166540869.319 736.190700@79g2 000cws.googlegr oups.com"Dilip" <rdilipk@lycos. comwrites:
      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:
      ....
      float f = 59.89F;
      /* the following line caused problems */
      double d = f;
      d will be approximately equal to 59.89 with the same precision as f
      /* they ended up solving it like this */
      f *= 1000.0;
      By sheer luck (due to the rounding rules) f is exactly equal to 59890.
      (You could even use 100 here with exactly the same results.)
      double dd = (double)f / 1000.0;
      And so this is a better approximation in double precision of 59.89.
      I see what is being done but why does the latter make the situation
      better?
      It is only luck. For other values of f it could fail and dd could
      (I think) even be worse than d.
      (consider 'f' in real life to hold stock prices)
      Consider not to use floating point for stock prices. Floating point
      inherently carries imprecision (especially if you want to do decimal
      calculations), which you do not want with stock prices.
      --
      dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
      home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

      Comment

      • Dik T. Winter

        #18
        Re: converting float to double

        In article <1166563496.656 669.292300@79g2 000cws.googlegr oups.com"Dilip" <rdilipk@lycos. comwrites:
        ....
        I am showing exactly what is being done in our codebase. Why do you
        say there is a compiler bug?
        There is indeed none, but you are misunderstandin g floating point.
        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).
        They do not vary, but you should print with sufficient precision.
        The exact value stored in both f and d is:
        59.889999389648 4375
        The
        multiplication/division to 1000.0 however produces 59.890000000000 001
        in dd.
        Actually the value stored in dd is:
        59.890000000000 000568434188608 080148696899414 0625
        But as I stated in another article, it is only luck that this value is
        larger than 59.89.
        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.
        Probably not rounding was done but truncation. In that case
        when d * 100 is truncated to int it will indeed give 59.88 and
        dd * 100 is truncated to 59.89. I can come up with initial values
        where this is all reversed. And it is even platform dependent.
        See message <1166545371.011 668.212280@48g2 000cwx.googlegr oups.com>
        in comp.arch.arith metic and the associated thread.
        It was off by a penny and that
        triggered major problems in other calculations.
        If off by a penny triggers major problems, you should *really* consider
        using integer arithmetic in pennies.
        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"?
        Use 64 bit integers for the amounts in pennies. When you use floating
        point and store the amount in dollars you should not be surprised that
        after a number of calculations the result is off by a penny (or perhaps
        more). Floating point variables can not store amounts in dollars with
        precision upto pennies.
        --
        dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
        home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

        Comment

        • Keith Thompson

          #19
          Re: converting float to double

          "Malcolm" <regniztar@btin ternet.comwrite s:
          <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.
          For certain values of "gracefully ".

          In some contexts, I would think that a one-penny error in a
          multi-trillion pound calculation ("trillion" meaning 10**12) would be
          considered unacceptable.

          64-bit integers should be more than enough to handle anything short of
          really extreme hyperinflation with no errors -- assuming that
          addition, subtraction, and multiplication by whole numbers are the
          only required operations.

          Compound interest introduces some interesting problems, but I think
          there are very specific rules for how to do those calculations. I
          suspect floating-point would not implement those rules correctly.

          Warning: I'm musing about stuff I've heard about here and there, but
          in which I have no particular expertise.

          --
          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

          • Keith Thompson

            #20
            Re: converting float to double

            "Dik T. Winter" <Dik.Winter@cwi .nlwrites:
            [...]
            Consider not to use floating point for stock prices. Floating point
            inherently carries imprecision (especially if you want to do decimal
            calculations), which you do not want with stock prices.
            If you need to do calculations with stock prices, find out what the
            formal rules are for doing those calculations. (I have no idea what
            those rules are, or where you'd find out about them.) Once you've
            done that, implement those rules. ("How?" "Correctly. ")

            --
            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

            • Dilip

              #21
              Re: converting float to double

              Dik T. Winter wrote:
              In article <1166540869.319 736.190700@79g2 000cws.googlegr oups.com"Dilip" <rdilipk@lycos. comwrites:
              (consider 'f' in real life to hold stock prices)
              >
              Consider not to use floating point for stock prices. Floating point
              inherently carries imprecision (especially if you want to do decimal
              calculations), which you do not want with stock prices.
              THis isn't always possible. The market data vendor I connect to
              insists that I read the stock prices as float. So when I reach into
              the byte-stream I will have to memcpy sizeof(float) number of bytes.
              Since everywhere else the system uses double to hold these prices, I
              had no choice but to stuff that retreived float value into a double
              causing all these problems.

              Comment

              • Random832

                #22
                Re: converting float to double

                2006-12-20 <1166638626.284 524.20130@79g20 00cws.googlegro ups.com>,
                Dilip wrote:
                Dik T. Winter wrote:
                >In article <1166540869.319 736.190700@79g2 000cws.googlegr oups.com"Dilip" <rdilipk@lycos. comwrites:
                > (consider 'f' in real life to hold stock prices)
                >>
                >Consider not to use floating point for stock prices. Floating point
                >inherently carries imprecision (especially if you want to do decimal
                >calculations ), which you do not want with stock prices.
                >
                THis isn't always possible. The market data vendor I connect to
                insists that I read the stock prices as float.
                Get a new vendor?
                So when I reach into the byte-stream I will have to memcpy
                sizeof(float) number of bytes. Since everywhere else the system uses
                double to hold these prices, I had no choice but to stuff that
                retreived float value into a double causing all these problems.
                Well - if you can't get a better vendor, the best way would be to do this:

                #include <math.h>
                //...
                float floating_price;
                long int price_cents;
                //...
                price_cents = round(f*100.);

                That way you'll actually get the value to the nearest cent, instead of
                doing "voodoo magic" that happens to get the right answer in one
                specific case you tested it on.

                If you need tenths of a cent, use 1000. there, etc, whatever precision
                you need. From that point, use the integer representation throughout
                your program.

                Comment

                • Ben Pfaff

                  #23
                  Re: converting float to double

                  Random832 <random@random. yi.orgwrites:
                  Well - if you can't get a better vendor, the best way would be to do this:
                  >
                  #include <math.h>
                  //...
                  float floating_price;
                  long int price_cents;
                  //...
                  price_cents = round(f*100.);
                  For what it's worth, the round function is new in C99.
                  --
                  "IMO, Perl is an excellent language to break your teeth on"
                  --Micah Cowan

                  Comment

                  • Ernie Wright

                    #24
                    Re: converting float to double

                    Dilip wrote:
                    Dik T. Winter wrote:
                    >
                    >Consider not to use floating point for stock prices.
                    >
                    THis isn't always possible. The market data vendor I connect to
                    insists that I read the stock prices as float. So when I reach into
                    the byte-stream I will have to memcpy sizeof(float) number of bytes.
                    Since everywhere else the system uses double to hold these prices, I
                    had no choice but to stuff that retreived float value into a double
                    causing all these problems.
                    Putting float values into doubles probably isn't the cause of your
                    problems. A double will hold exactly the same value as the original
                    float.

                    In most implementations , both float and double represent numbers as

                    (1 + m / 2^b) * 2^e

                    where m is (part of) the mantissa, b is the number of bits in m, e is
                    the exponent, and '^' denotes exponentiation. b is 23 for floats and 53
                    for doubles. Given the m, b, e of a float, you get the double with

                    m <<= 30
                    b += 30
                    e = e

                    Or to put it another way,

                    float: 59.89 - (1 + 7311196 / 8388608) * 32
                    double: 59.89 - (1 + (7311196 << 30) / (8388608 << 30)) * 32

                    The values are identical, so the problems must be arising from what is
                    being done with them.

                    - Ernie http://home.comcast.net/~erniew

                    Comment

                    • William Hughes

                      #25
                      Re: converting float to double


                      Ernie Wright wrote:
                      Dilip wrote:
                      >
                      Dik T. Winter wrote:
                      Consider not to use floating point for stock prices.
                      THis isn't always possible. The market data vendor I connect to
                      insists that I read the stock prices as float. So when I reach into
                      the byte-stream I will have to memcpy sizeof(float) number of bytes.
                      Since everywhere else the system uses double to hold these prices, I
                      had no choice but to stuff that retreived float value into a double
                      causing all these problems.
                      >
                      Putting float values into doubles probably isn't the cause of your
                      problems. A double will hold exactly the same value as the original
                      float.
                      >
                      True, but irrelevent.

                      Mathematically

                      (float) (1000.0 * f) =/= 1000.0 * f

                      There is a small bit of rounding. So

                      (double)( (float) 1000.0*f)/ 1000.0 =/= f

                      In the present case we start out with a value just less than a multiple
                      of
                      a whole cent, and end up with a value just greater than a multiple
                      of a cent.

                      - William Hughes

                      Comment

                      • William Hughes

                        #26
                        Re: converting float to double


                        Dilip wrote:
                        Dik T. Winter wrote:
                        In article <1166540869.319 736.190700@79g2 000cws.googlegr oups.com"Dilip" <rdilipk@lycos. comwrites:
                        (consider 'f' in real life to hold stock prices)
                        Consider not to use floating point for stock prices. Floating point
                        inherently carries imprecision (especially if you want to do decimal
                        calculations), which you do not want with stock prices.
                        >
                        THis isn't always possible. The market data vendor I connect to
                        insists that I read the stock prices as float. So when I reach into
                        the byte-stream I will have to memcpy sizeof(float) number of bytes.
                        Since everywhere else the system uses double to hold these prices, I
                        had no choice but to stuff that retreived float value into a double
                        causing all these problems.
                        A system that uses floating point variables to store prices should
                        work correctly if a price is just above or just below the
                        correct price (e.g for a price of 0.010001 dollars or 0.009998
                        dollars).
                        The system you use does not have this property. It needs
                        to be fixed. However, it appears that by management fiat you have
                        to use this system, and any problems are deemed yours.

                        A possible workaround:

                        Read the prices as float
                        Round to the nearest cent or tenth of a cent (*)
                        Convert to double
                        Add a fudge factor of 0.00000001

                        Now your prices will be subtly wrong, but they will be subtly wrong in
                        the correct direction. This should work as well as the
                        (double)(f*1000 .0)/1000.0
                        kludge, and will work for any value. (adding the fudge factor may or
                        may
                        not be necessary. It would not be necessary, but for the fact that you
                        have to use a broken system. There may be a price that when expressed
                        as a double is slightly below the true price.)

                        * if you don't have access to a C99 type round() function, roll your
                        own
                        (e.g. floor(100.0*dd + 0.5)/100.0) or sprintf the value and sscanf
                        it back

                        - William
                        Hughes

                        Comment

                        • CBFalconer

                          #27
                          Re: converting float to double

                          Dilip wrote:
                          Dik T. Winter wrote:
                          >"Dilip" <rdilipk@lycos. comwrites:
                          >>
                          >>(consider 'f' in real life to hold stock prices)
                          >>
                          >Consider not to use floating point for stock prices. Floating
                          >point inherently carries imprecision (especially if you want to
                          >do decimal calculations), which you do not want with stock prices.
                          >
                          THis isn't always possible. The market data vendor I connect to
                          insists that I read the stock prices as float. So when I reach
                          into the byte-stream I will have to memcpy sizeof(float) number of
                          bytes. Since everywhere else the system uses double to hold these
                          prices, I had no choice but to stuff that retreived float value
                          into a double causing all these problems.
                          This is inherently impossible. While some systems use IEEE float
                          format, many do not, so you don't even know the bit pattern coming
                          in. Are you sure you aren't reading and converting a text stream?
                          If so all you have to do is write a suitable parser for a
                          particular text format, say dddd.dd, where d is a digit.

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


                          Comment

                          • CBFalconer

                            #28
                            Re: converting float to double

                            Ben Pfaff wrote:
                            Random832 <random@random. yi.orgwrites:
                            >
                            >Well - if you can't get a better vendor, the best way would be
                            >to do this:
                            >>
                            > #include <math.h>
                            > //...
                            > float floating_price;
                            > long int price_cents;
                            > //...
                            > price_cents = round(f*100.);
                            >
                            For what it's worth, the round function is new in C99.
                            and unnecessary.

                            price_cents = 100 * floating_price + 0.5;

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


                            Comment

                            • Random832

                              #29
                              Re: converting float to double

                              2006-12-20 <4589970F.A5A43 40D@yahoo.com>,
                              CBFalconer wrote:
                              Ben Pfaff wrote:
                              >Random832 <random@random. yi.orgwrites:
                              >>
                              >>Well - if you can't get a better vendor, the best way would be
                              >>to do this:
                              >>>
                              >> #include <math.h>
                              >> //...
                              >> float floating_price;
                              >> long int price_cents;
                              >> //...
                              >> price_cents = round(f*100.);
                              >>
                              >For what it's worth, the round function is new in C99.
                              >
                              and unnecessary.
                              >
                              price_cents = 100 * floating_price + 0.5;
                              I thought that was implementation-defined.

                              Comment

                              • William Hughes

                                #30
                                Re: converting float to double


                                Random832 wrote:
                                2006-12-20 <4589970F.A5A43 40D@yahoo.com>,
                                CBFalconer wrote:
                                Ben Pfaff wrote:
                                Random832 <random@random. yi.orgwrites:
                                >
                                >Well - if you can't get a better vendor, the best way would be
                                >to do this:
                                >>
                                > #include <math.h>
                                > //...
                                > float floating_price;
                                > long int price_cents;
                                > //...
                                > price_cents = round(f*100.);
                                >
                                For what it's worth, the round function is new in C99.
                                and unnecessary.

                                price_cents = 100 * floating_price + 0.5;
                                >
                                I thought that was implementation-defined.
                                Not if price_cents is assumed to be greater than or equal to 0.

                                - William Hughes

                                Comment

                                Working...