Rounding double

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

    Rounding double

    Hi

    Does any body know, how to round a double value with a specific number
    of digits after the decimal points?

    A function like this:

    RoundMyDouble (double &value, short numberOfPrecisi ons)

    It then updates the value with numberOfPrecisi ons after the decimal
    point.

    Any help is appreciated.

    Thanks.
    md
  • suresh

    #2
    Re: Rounding double

    On Nov 22, 10:39 am, md <mojtaba.da...@ gmail.comwrote:
    Hi
    >
    Does any body know, how to round a double value with a specific number
    of digits after the decimal points?
    >
    A function like this:
    >
    RoundMyDouble (double &value, short numberOfPrecisi ons)
    >
    {
    int p = pow(10, numberOfPrecisi ons);
    value = (int)(value * p + 0.5) / (double)p;
    }

    Comment

    • David Harmon

      #3
      Re: Rounding double

      On Wed, 21 Nov 2007 21:39:57 -0800 (PST) in comp.lang.c++, md
      <mojtaba.danai@ gmail.comwrote,
      >Hi
      >
      >Does any body know, how to round a double value with a specific number
      >of digits after the decimal points?
      >
      >A function like this:
      >
      >RoundMyDoubl e (double &value, short numberOfPrecisi ons)
      You cannot in general round a double value to a specific number of
      digits, because doubles are not decimal. Save your rounding 'til you
      are ready to format the number into a decimal string.

      See "What Every Computer Scientist Should Know About Floating-Point
      Arithmetic" http://docs.sun.com/source/806-3568/ncg_goldberg.html

      Comment

      • Richard Heathfield

        #4
        Re: Rounding double

        md said:
        Hi
        >
        Does any body know, how to round a double value with a specific number
        of digits after the decimal points?
        >
        A function like this:
        >
        RoundMyDouble (double &value, short numberOfPrecisi ons)
        >
        It then updates the value with numberOfPrecisi ons after the decimal
        point.
        Well, you have a syntax error right there: double &value isn't legal. You
        presumably meant double *value.

        Elsethread, you were given this suggestion (suitably modified so that it
        will actually compile, and with a driver added):

        #include <stdio.h>
        #include <math.h>

        void RoundMyDouble (double *value, short numberOfPrecisi ons)

        {
        int p = pow(10, numberOfPrecisi ons);
        *value = (int)(*value * p + 0.5) / (double)p;
        }

        int main(void)
        {
        double v = 3.1415926535897 9323846;
        short int ndp = 0;
        while(ndp < 10)
        {
        double newv = v;
        RoundMyDouble(& newv, ndp);
        printf("%.16f, \"rounded\" to %hd decimals, is %.16f\n",
        v,
        ndp++,
        newv);
        }

        return 0;
        }

        Here are the test results:

        3.1415926535897 931, "rounded" to 0 decimals, is 3.0000000000000 000
        3.1415926535897 931, "rounded" to 1 decimals, is 3.1000000000000 001
        3.1415926535897 931, "rounded" to 2 decimals, is 3.1400000000000 001
        3.1415926535897 931, "rounded" to 3 decimals, is 3.1419999999999 999
        3.1415926535897 931, "rounded" to 4 decimals, is 3.1415999999999 999
        3.1415926535897 931, "rounded" to 5 decimals, is 3.1415899999999 999
        3.1415926535897 931, "rounded" to 6 decimals, is 3.1415929999999 999
        3.1415926535897 931, "rounded" to 7 decimals, is 3.1415926999999 999
        3.1415926535897 931, "rounded" to 8 decimals, is 3.1415926500000 002
        3.1415926535897 931, "rounded" to 9 decimals, is -2.1474836480000 001

        As you can see, it doesn't really round at all. It nudges the value close
        to what is required, but doesn't hit the requirement right on the nose.
        And that last result looks like a lot of fun, doesn't it? :-)

        --
        Richard Heathfield <http://www.cpax.org.uk >
        Email: -http://www. +rjh@
        Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
        "Usenet is a strange place" - dmr 29 July 1999

        Comment

        • Jim Langston

          #5
          Re: Rounding double

          "Richard Heathfield" <rjh@see.sig.in validwrote in message
          news:v9qdnXSpzf rRsNjanZ2dnUVZ8 sWhnZ2d@bt.com. ..
          md said:
          >
          >Hi
          >>
          >Does any body know, how to round a double value with a specific number
          >of digits after the decimal points?
          >>
          >A function like this:
          >>
          >RoundMyDoubl e (double &value, short numberOfPrecisi ons)
          >>
          >It then updates the value with numberOfPrecisi ons after the decimal
          >point.
          >
          Well, you have a syntax error right there: double &value isn't legal. You
          presumably meant double *value.
          Actually, double& value is legal in C++ but not C. It declares value as a
          non-constant reference. It is not legal in C however. This was cross posted
          to two newsgroups (c.l.c++ and c.l.c) which is usually a bad idea just for
          this problem.

          [snip rest of reply]


          Comment

          • Richard Heathfield

            #6
            Re: Rounding double

            Jim Langston said:
            "Richard Heathfield" <rjh@see.sig.in validwrote in message
            news:v9qdnXSpzf rRsNjanZ2dnUVZ8 sWhnZ2d@bt.com. ..
            >>
            >Well, you have a syntax error right there: double &value isn't legal.
            >You presumably meant double *value.
            >
            Actually, double& value is legal in C++ but not C.
            Right - but of course a cross-posted article should "work" in all the
            groups into which it's posted. Here, the post worked in clc++ but not in
            clc, so either it should not have been posted to clc or the pointer syntax
            should have been used rather than the reference syntax (at which point, of
            course, there would have been howls of protest from the clc++ crowd, and
            perhaps rightly so).
            This was cross
            posted to two newsgroups (c.l.c++ and c.l.c) which is usually a bad idea
            just for this problem.
            Indeed.

            --
            Richard Heathfield <http://www.cpax.org.uk >
            Email: -http://www. +rjh@
            Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
            "Usenet is a strange place" - dmr 29 July 1999

            Comment

            • md

              #7
              Re: Rounding double

              On Nov 22, 6:21 pm, Richard Heathfield <r...@see.sig.i nvalidwrote:
              md said:
              >
              Hi
              >
              Does any body know, how to round a double value with a specific number
              of digits after the decimal points?
              >
              A function like this:
              >
              RoundMyDouble (double &value, short numberOfPrecisi ons)
              >
              It then updates the value with numberOfPrecisi ons after the decimal
              point.
              >
              Well, you have a syntax error right there: double &value isn't legal. You
              presumably meant double *value.
              >
              Elsethread, you were given this suggestion (suitably modified so that it
              will actually compile, and with a driver added):
              >
              #include <stdio.h>
              #include <math.h>
              >
              void RoundMyDouble (double *value, short numberOfPrecisi ons)
              >
              {
              int p = pow(10, numberOfPrecisi ons);
              *value = (int)(*value * p + 0.5) / (double)p;
              >
              }
              >
              int main(void)
              {
              double v = 3.1415926535897 9323846;
              short int ndp = 0;
              while(ndp < 10)
              {
              double newv = v;
              RoundMyDouble(& newv, ndp);
              printf("%.16f, \"rounded\" to %hd decimals, is %.16f\n",
              v,
              ndp++,
              newv);
              }
              >
              return 0;
              >
              }
              >
              Here are the test results:
              >
              3.1415926535897 931, "rounded" to 0 decimals, is 3.0000000000000 000
              3.1415926535897 931, "rounded" to 1 decimals, is 3.1000000000000 001
              3.1415926535897 931, "rounded" to 2 decimals, is 3.1400000000000 001
              3.1415926535897 931, "rounded" to 3 decimals, is 3.1419999999999 999
              3.1415926535897 931, "rounded" to 4 decimals, is 3.1415999999999 999
              3.1415926535897 931, "rounded" to 5 decimals, is 3.1415899999999 999
              3.1415926535897 931, "rounded" to 6 decimals, is 3.1415929999999 999
              3.1415926535897 931, "rounded" to 7 decimals, is 3.1415926999999 999
              3.1415926535897 931, "rounded" to 8 decimals, is 3.1415926500000 002
              3.1415926535897 931, "rounded" to 9 decimals, is -2.1474836480000 001
              >
              As you can see, it doesn't really round at all. It nudges the value close
              to what is required, but doesn't hit the requirement right on the nose.
              And that last result looks like a lot of fun, doesn't it? :-)
              >
              --
              Richard Heathfield <http://www.cpax.org.uk >
              Email: -http://www. +rjh@
              Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
              "Usenet is a strange place" - dmr 29 July 1999
              Yes, Richard. That is the result I also got.
              Sorry for sending the message to two different groups.

              Can some one give a solution for how to solve this problem?

              Thanks again
              md

              Comment

              • md

                #8
                Re: Rounding double

                On Nov 22, 4:56 pm, David Harmon <sou...@netcom. comwrote:
                On Wed, 21 Nov 2007 21:39:57 -0800 (PST) in comp.lang.c++, md
                <mojtaba.da...@ gmail.comwrote,
                >
                Hi
                >
                Does any body know, how to round a double value with a specific number
                of digits after the decimal points?
                >
                A function like this:
                >
                RoundMyDouble (double &value, short numberOfPrecisi ons)
                >
                You cannot in general round a double value to a specific number of
                digits, because doubles are not decimal. Save your rounding 'til you
                are ready to format the number into a decimal string.
                >
                See "What Every Computer Scientist Should Know About Floating-Point
                Arithmetic" http://docs.sun.com/source/806-3568/ncg_goldberg.htm
                What do you mean David? Is ther a solution for this?
                Thanks.

                Regards,
                md

                Comment

                • md

                  #9
                  Re: Rounding double

                  On Nov 22, 4:49 pm, suresh <mail2msur...@g mail.comwrote:
                  On Nov 22, 10:39 am, md <mojtaba.da...@ gmail.comwrote: Hi
                  >
                  Does any body know, how to round a double value with a specific number
                  of digits after the decimal points?
                  >
                  A function like this:
                  >
                  RoundMyDouble (double &value, short numberOfPrecisi ons)
                  >
                  {
                  int p = pow(10, numberOfPrecisi ons);
                  value = (int)(value * p + 0.5) / (double)p;
                  >
                  >
                  >
                  }- Hide quoted text -
                  >
                  - Show quoted text -
                  I tried that before but it does not work!

                  md

                  Comment

                  • Richard Heathfield

                    #10
                    Re: Rounding double

                    md said:
                    Does any body know, how to round a double value with a specific number
                    of digits after the decimal points?
                    >>
                    <snip>
                    >
                    Yes, Richard. That is the result I also got.
                    Sorry for sending the message to two different groups.
                    >
                    Can some one give a solution for how to solve this problem?
                    It has already been explained to you that this simply can't be done (in
                    general). Let's take a frinstance, and pi/10 is as good as anything else
                    for this purpose:

                    0.3141592653589 89323846...

                    and you want to round it to 6 decimal places. So you want the value of the
                    double to be precisely 0.314159.

                    Let's see how we might represent such a number, using pure binary notation.
                    (Floating point numbers aren't actually stored in pure binary, but it's
                    not all /that/ different, it's the same underlying problem, and this one
                    is easier to explain and easier to follow.)

                    In pure binary notation, we use a binary point rather than a decimal point
                    ("radix point" is an umbrella term that covers them both, and others). The
                    column to the immediate left of the binary point is worth 1. Every column
                    to the right of the binary point is worth half as much as its immediate
                    left neighbour. Thus, 0.5 (decimal) is 0.1 (binary), 0.25 (decimal) is
                    0.01 (binary), 0.75 (decimal) is 0.11 (binary), and so on.

                    So how do we represent EXACTLY 0.314159 in pure binary notation? How many
                    bits do you think we'll need?

                    0.1 = 1/2 = 0.5 - too large
                    0.01 = 1/4 = 0.25 - too small
                    0.011 = 3/8 = 0.375 - too large
                    0.0101 = 5/16 = 0.3125 - too small
                    0.01011 = 11/32 = 0.34375 - too large
                    0.010101 = 21/64 = 0.328125 - too large
                    0.0101001 = 41/128 = 0.3203125 - too large
                    0.01010001 = 81/256 = 0.31640625 - too large
                    0.010100001 = 161/512 = 0.314453125 - too large
                    0.0101000001 = 321/1024 = 0.3134765625 - too small
                    0.01010000011 = 643/2048 = 0.31396484375 - too small
                    0.010100000111 = 1287/4096 = 0.314208984375 - too large
                    0.0101000001101 = 2573/8192 = 0.3140869140625 - too small
                    0.0101000001101 1 = 5147/16384 = 0.3141479492187 5 - too small
                    0.0101000001101 11 = 10295/32768 = 0.3141784667968 75 - too large
                    0.0101000001101 101 = 20589/65536 = 0.3141632080078 125 - too large

                    Sixteen bits so far, and we're not even close.

                    So instead of trying to do the impossible, just round the displayed value
                    rather than the stored value. For example, if you want to display pi/10 to
                    six places, just do this: printf("%.6f\n" , pi/10);

                    --
                    Richard Heathfield <http://www.cpax.org.uk >
                    Email: -http://www. +rjh@
                    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
                    "Usenet is a strange place" - dmr 29 July 1999

                    Comment

                    • jacob navia

                      #11
                      Re: Rounding double

                      md wrote:
                      On Nov 22, 4:49 pm, suresh <mail2msur...@g mail.comwrote:
                      >On Nov 22, 10:39 am, md <mojtaba.da...@ gmail.comwrote: Hi
                      >>
                      >>Does any body know, how to round a double value with a specific number
                      >>of digits after the decimal points?
                      >>A function like this:
                      >>RoundMyDoub le (double &value, short numberOfPrecisi ons)
                      >{
                      > int p = pow(10, numberOfPrecisi ons);
                      > value = (int)(value * p + 0.5) / (double)p;
                      >>
                      >>
                      >>
                      >}- Hide quoted text -
                      >>
                      >- Show quoted text -
                      >
                      I tried that before but it does not work!
                      >
                      md
                      This can go beyond 9:
                      #include <stdio.h>
                      #include <math.h>

                      void RoundMyDouble (long double *value, short numberOfPrecisi ons)

                      {
                      long long p = powl(10.0L, numberOfPrecisi ons);
                      *value = (long long)(*value * p + 0.5L) / (double)p;
                      }

                      int main(void)
                      {
                      long double v = 3.1415926535897 932384626L;
                      short int ndp = 0;
                      while(ndp < 20)
                      {
                      long double newv = v;
                      RoundMyDouble(& newv, ndp);
                      printf("%.21Lf, \"rounded\" to %hd decimals, is %.21Lf\n",
                      v,
                      ndp++,
                      newv);
                      }

                      return 0;
                      }

                      You will need a modern C compiler to use this (C99 standard).
                      Using lcc-win I get:
                      3.1415926535897 932390: 0 decimals 3.0000000000000 000000
                      3.1415926535897 932390: 1 decimals 3.1000000000000 000000
                      3.1415926535897 932390: 2 decimals 3.1400000000000 000000
                      3.1415926535897 932390: 3 decimals 3.1420000000000 000000
                      3.1415926535897 932390: 4 decimals 3.1416000000000 000000
                      3.1415926535897 932390: 5 decimals 3.1415900000000 000000
                      3.1415926535897 932390: 6 decimals 3.1415930000000 000000
                      3.1415926535897 932390: 7 decimals 3.1415927000000 000000
                      3.1415926535897 932390: 8 decimals 3.1415926500000 000000
                      3.1415926535897 932390: 9 decimals 3.1415926540000 000000
                      3.1415926535897 932390: 10 decimals 3.1415926536000 000000
                      3.1415926535897 932390: 11 decimals 3.1415926535900 000000
                      3.1415926535897 932390: 12 decimals 3.1415926535900 000000
                      3.1415926535897 932390: 13 decimals 3.1415926535898 000000
                      3.1415926535897 932390: 14 decimals 3.1415926535897 900000
                      3.1415926535897 932390: 15 decimals 3.1415926535897 930000
                      3.1415926535897 932390: 16 decimals 3.1415926535897 932000
                      3.1415926535897 932390: 17 decimals 3.1415926535897 932400
                      3.1415926535897 932390: 18 decimals 3.1415926535897 932390
                      3.1415926535897 932390: 19 decimals 1.0000000000000 000000

                      --
                      jacob navia
                      jacob at jacob point remcomp point fr
                      logiciels/informatique

                      Comment

                      • Richard Heathfield

                        #12
                        Re: Rounding double

                        jacob navia said:

                        <snip>
                        #include <stdio.h>
                        #include <math.h>
                        >
                        void RoundMyDouble (long double *value, short numberOfPrecisi ons)
                        >
                        {
                        long long p = powl(10.0L, numberOfPrecisi ons);
                        *value = (long long)(*value * p + 0.5L) / (double)p;
                        }
                        >
                        int main(void)
                        {
                        long double v = 3.1415926535897 932384626L;
                        short int ndp = 0;
                        while(ndp < 20)
                        {
                        long double newv = v;
                        RoundMyDouble(& newv, ndp);
                        printf("%.21Lf, \"rounded\" to %hd decimals, is %.21Lf\n",
                        v,
                        ndp++,
                        newv);
                        }
                        >
                        return 0;
                        }
                        >
                        You will need a modern C compiler to use this (C99 standard).
                        Using lcc-win I get:
                        >
                        <snip>
                        >3.141592653589 7932390: 19 decimals 1.0000000000000 000000
                        Do you think that's a compiler bug, or a programmer bug?

                        --
                        Richard Heathfield <http://www.cpax.org.uk >
                        Email: -http://www. +rjh@
                        Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
                        "Usenet is a strange place" - dmr 29 July 1999

                        Comment

                        • jacob navia

                          #13
                          Re: Rounding double

                          Richard Heathfield wrote:
                          jacob navia said:
                          >
                          <snip>
                          >
                          >#include <stdio.h>
                          >#include <math.h>
                          >>
                          >void RoundMyDouble (long double *value, short numberOfPrecisi ons)
                          >>
                          >{
                          > long long p = powl(10.0L, numberOfPrecisi ons);
                          > *value = (long long)(*value * p + 0.5L) / (double)p;
                          >}
                          >>
                          >int main(void)
                          >{
                          > long double v = 3.1415926535897 932384626L;
                          > short int ndp = 0;
                          > while(ndp < 20)
                          > {
                          > long double newv = v;
                          > RoundMyDouble(& newv, ndp);
                          > printf("%.21Lf, \"rounded\" to %hd decimals, is %.21Lf\n",
                          > v,
                          > ndp++,
                          > newv);
                          > }
                          >>
                          > return 0;
                          >}
                          >>
                          >You will need a modern C compiler to use this (C99 standard).
                          >Using lcc-win I get:
                          >>
                          <snip>
                          >
                          >>3.14159265358 97932390: 19 decimals 1.0000000000000 000000
                          >
                          Do you think that's a compiler bug, or a programmer bug?
                          >
                          output of gcc:
                          3.1415926535897 932385: 0 decimals 3.0000000000000 000000
                          [snip]
                          3.1415926535897 932385: 17 decimals 3.1415926535897 932400
                          3.1415926535897 932385: 18 decimals 3.1415926535897 932389
                          3.1415926535897 932385: 19 decimals 1.0000000000000 000000

                          If it is a compiler bug, it is a shared compiler bug.

                          It isn't a programmer bug either. Long long has a finite
                          number of decimal digits as you may know.

                          18.
                          --
                          jacob navia
                          jacob at jacob point remcomp point fr
                          logiciels/informatique

                          Comment

                          • Marco Manfredini

                            #14
                            Re: Rounding double

                            jacob navia wrote:
                            md wrote:
                            >On Nov 22, 4:49 pm, suresh <mail2msur...@g mail.comwrote:
                            >>On Nov 22, 10:39 am, md <mojtaba.da...@ gmail.comwrote: Hi
                            >>>
                            >>>Does any body know, how to round a double value with a specific
                            >>>number of digits after the decimal points?
                            >>>A function like this:
                            >>>RoundMyDoubl e (double &value, short numberOfPrecisi ons)
                            >>{
                            >> int p = pow(10, numberOfPrecisi ons);
                            >> value = (int)(value * p + 0.5) / (double)p;
                            >>>
                            >>>
                            >>>
                            >>}- Hide quoted text -
                            >>>
                            >>- Show quoted text -
                            >>
                            >I tried that before but it does not work!
                            >>
                            >md
                            >
                            This can go beyond 9:
                            #include <stdio.h>
                            #include <math.h>
                            >
                            void RoundMyDouble (long double *value, short numberOfPrecisi ons)
                            >
                            {
                            long long p = powl(10.0L, numberOfPrecisi ons);
                            *value = (long long)(*value * p + 0.5L) / (double)p;
                            }
                            I have floor(). It even goes past 11!


                            --
                            IYesNo yes=YesNoFactor y.getFactoryIns tance().YES;
                            yes.getDescript ion().equals(ar ray[0].toUpperCase()) ;

                            Comment

                            • James Kuyper

                              #15
                              Re: Rounding double

                              jacob navia wrote:
                              Richard Heathfield wrote:
                              >jacob navia said:
                              >>
                              ><snip>
                              >>
                              >>#include <stdio.h>
                              >>#include <math.h>
                              >>>
                              >>void RoundMyDouble (long double *value, short numberOfPrecisi ons)
                              >>>
                              >>{
                              >> long long p = powl(10.0L, numberOfPrecisi ons);
                              >> *value = (long long)(*value * p + 0.5L) / (double)p;
                              >>}
                              >>>
                              >>int main(void)
                              >>{
                              >> long double v = 3.1415926535897 932384626L;
                              >> short int ndp = 0;
                              >> while(ndp < 20)
                              >> {
                              >> long double newv = v;
                              >> RoundMyDouble(& newv, ndp);
                              >> printf("%.21Lf, \"rounded\" to %hd decimals, is %.21Lf\n",
                              >> v,
                              >> ndp++,
                              >> newv);
                              >> }
                              >>>
                              >> return 0;
                              >>}
                              >>>
                              >>You will need a modern C compiler to use this (C99 standard).
                              >>Using lcc-win I get:
                              >>>
                              ><snip>
                              >>
                              >>>3.1415926535 897932390: 19 decimals 1.0000000000000 000000
                              >>
                              >Do you think that's a compiler bug, or a programmer bug?
                              >>
                              >
                              output of gcc:
                              3.1415926535897 932385: 0 decimals 3.0000000000000 000000
                              [snip]
                              3.1415926535897 932385: 17 decimals 3.1415926535897 932400
                              3.1415926535897 932385: 18 decimals 3.1415926535897 932389
                              3.1415926535897 932385: 19 decimals 1.0000000000000 000000
                              >
                              If it is a compiler bug, it is a shared compiler bug.
                              >
                              It isn't a programmer bug either. Long long has a finite
                              number of decimal digits as you may know.
                              Which makes use of long long a programming error. You should have used
                              one of the rounding functions like floorl(), nearbyintl(), rintl(), or
                              roundl(), instead of conversion to long long. Even with that fix, the
                              algorithm you choose needlessly results in overflow (or underflow, for
                              negative values of numberOfPrecisi ons) in some cases.

                              I say that it's needless (and therefore a programming error) because you
                              can avoid both problems by using sprintf() and sscanf(). There are more
                              efficient ways of doing it, but that one is sufficient.

                              Comment

                              Working...