Floating point arithmetic.

Discussion in 'C++' started by Amit Bhatia, Jul 11, 2004.

  1. Amit Bhatia

    Amit Bhatia Guest

    Hi there.
    I am cross posting this on comp.lang.c as well: sorry for same.
    The problem I am facing is as follows:
    For example:
    double a= 0.15;
    double b=2.4;
    const double VERYTINY =1.e-10;
    I know b/a = 16 and hence the remainder is zero; but I am not
    able to find any suitable thing to encode it into in c.
    for example (fmod(b,a)>VERYTINY) returns true!
    Now for this particular instance, (fmodf(b,a)>VERYTINY)
    does return false.
    But now if
    a=0.15;
    b=4.5;
    then fmodf and fmod both don't help...

    any suggestions on this?
    I was pointed to a reference on floating point arithmetic, where they talk
    of ulps etc, but is there a small function or fix to deal with this problem
    available somewhere?

    thanks,
    amit.
     
    Amit Bhatia, Jul 11, 2004
    #1
    1. Advertising

  2. "Amit Bhatia" <> wrote:

    > The problem I am facing is as follows:
    > For example:


    Example of what? It makes more sense to state the
    thing you want to give an example of, before giving
    examples of it.

    > double a= 0.15;
    > double b=2.4;
    > const double VERYTINY =1.e-10;
    > I know b/a = 16 and hence the remainder is zero;
    > but I am not able to find any suitable thing to
    > encode it into in c.


    Define "encode".

    Define "it".

    If you want to code b/a in C, the code is:

    b/a

    > for example


    Example of what? Please give some clue as to the thing
    you're trying to give an example OF, before giving
    examples!

    > (fmod(b,a)>VERYTINY) returns true!


    It returns false on my system. However, it seems to me
    you're pushing the granularity of type double to the max.
    Even if you WERE off by one part per 1e10, so what?
    That's one part per ten billion. Who cares?

    But if you really DO care, try acquiring a compiler that
    supports type "long double". Or, perhaps, use a computer
    with a 64-bit processor and compiler that defines "double"
    to be 64 bits. Even if 4 or so of those bits were used
    for sign and exponent, you'd still have a granularity of
    about 1 part per quintillion (1e18). More precision than
    you'll EVER need.

    > Now for this particular instance, (fmodf(b,a)>VERYTINY)
    > does return false.


    What is fmodf? That's not a part of the C or C++ std.
    libraries. I don't have it on my compiler (DJGPP) either.

    > But now if
    > a=0.15;
    > b=4.5;
    > then fmodf and fmod both don't help...


    I get b/a = 30 and (fmod(b,a)>VERYTINY) = false.

    What do YOU get?

    > any suggestions on this?


    Suggestions on what, precisely?

    > I was pointed to a reference on floating point
    > arithmetic, where they talk of ulps etc,


    What's "ulps"?

    > is there a small function or fix to deal with this problem
    > available somewhere?


    What problem are you trying to fix?

    --
    Cheers,
    Robbie Hatley
    Tustin, CA, USA

    http://home.pacbell.net/earnur/
     
    Robbie Hatley, Jul 11, 2004
    #2
    1. Advertising

  3. On Sun, 11 Jul 2004 01:17:09 -0700, Robbie Hatley <lonewolfintj at pacbell
    dot net> wrote:

    >
    >> I was pointed to a reference on floating point
    >> arithmetic, where they talk of ulps etc,

    >
    > What's "ulps"?
    >


    ULP stands for unit in the last place. Its a measure of rounding error and
    a common enough term in floating point arithmetic.

    john
     
    John Harrison, Jul 11, 2004
    #3
  4. On Sat, 10 Jul 2004 23:08:01 -0500, Amit Bhatia <> wrote:

    > Hi there.
    > I am cross posting this on comp.lang.c as well: sorry for same.
    > The problem I am facing is as follows:
    > For example:
    > double a= 0.15;
    > double b=2.4;
    > const double VERYTINY =1.e-10;
    > I know b/a = 16 and hence the remainder is zero; but I am not
    > able to find any suitable thing to encode it into in c.
    > for example (fmod(b,a)>VERYTINY) returns true!
    > Now for this particular instance, (fmodf(b,a)>VERYTINY)
    > does return false.
    > But now if
    > a=0.15;
    > b=4.5;
    > then fmodf and fmod both don't help...
    >
    > any suggestions on this?


    Maybe use a bigger value for VERYTINY.
    Maybe use integral or rational aritmetic.
    Maybe use fixed point arithmetic.

    > I was pointed to a reference on floating point arithmetic, where they
    > talk
    > of ulps etc, but is there a small function or fix to deal with this
    > problem
    > available somewhere?


    There is not easy answer to the problem of floating point rounding errors.
    The simplest thing is not to write code that depends on any particular
    exactness of floating point arithmetic. Obviously this is not always
    possible but it is possible more often than people think.

    So the asnwer to your question really depends on what kind of problem you
    are actually trying to solve.

    john
     
    John Harrison, Jul 11, 2004
    #4
  5. Amit Bhatia

    David Harmon Guest

    On Sat, 10 Jul 2004 23:08:01 -0500 in comp.lang.c++, Amit Bhatia
    <> wrote,
    >Hi there.
    > I am cross posting this on comp.lang.c as well: sorry for same.


    In fact you did so a few days ago and got some good tips.

    >The problem I am facing is as follows:
    > For example:
    > double a= 0.15;
    > double b=2.4;
    > const double VERYTINY =1.e-10;


    b = two and two fifths. Fifths can not be represented exactly in base
    two floating point format, so this number cannot be stored exactly.
    a is 16 times that, so of course has a similar approximation.

    And so on. Never expect any form of exactitude from any floating point
    operation, and your life will be less frustrating.

    >I know b/a = 16 and hence the remainder is zero; but I am not
    >able to find any suitable thing to encode it into in c.


    It may be close to zero, or it may be just less than 0.15.

    If you persist in this folly then I guess you need to test for both
    possibilities.
     
    David Harmon, Jul 11, 2004
    #5
  6. Amit Bhatia

    Subhash Guest

    Amit Bhatia <> wrote in message news:<ccqf0m$lfj$>...
    > Hi there.
    > I am cross posting this on comp.lang.c as well: sorry for same.
    > The problem I am facing is as follows:
    > For example:
    > double a= 0.15;
    > double b=2.4;
    > const double VERYTINY =1.e-10;
    > I know b/a = 16 and hence the remainder is zero; but I am not
    > able to find any suitable thing to encode it into in c.
    > for example (fmod(b,a)>VERYTINY) returns true!
    > Now for this particular instance, (fmodf(b,a)>VERYTINY)
    > does return false.
    > But now if
    > a=0.15;
    > b=4.5;
    > then fmodf and fmod both don't help...
    >
    > any suggestions on this?
    > I was pointed to a reference on floating point arithmetic, where they talk
    > of ulps etc, but is there a small function or fix to deal with this problem
    > available somewhere?
    >
    > thanks,
    > amit.



    int main() {
    double a = 0.15;
    double b = 2.4;
    const double VERYTINY =1.e-10;
    printf("%d", (fmod(b,a) > VERYTINY));
    return 0;
    }

    This gives me false!
     
    Subhash, Jul 11, 2004
    #6
  7. Amit Bhatia

    Arijit Guest

    Amit Bhatia <> wrote in message news:<ccqf0m$lfj$>...
    > Hi there.
    > I am cross posting this on comp.lang.c as well: sorry for same.
    > The problem I am facing is as follows:
    > For example:
    > double a= 0.15;
    > double b=2.4;
    > const double VERYTINY =1.e-10;
    > I know b/a = 16 and hence the remainder is zero; but I am not
    > able to find any suitable thing to encode it into in c.
    > for example (fmod(b,a)>VERYTINY) returns true!
    > Now for this particular instance, (fmodf(b,a)>VERYTINY)
    > does return false.
    > But now if
    > a=0.15;
    > b=4.5;
    > then fmodf and fmod both don't help...
    >
    > any suggestions on this?
    > I was pointed to a reference on floating point arithmetic, where they talk
    > of ulps etc, but is there a small function or fix to deal with this problem
    > available somewhere?
    >
    > thanks,
    > amit.



    Try the following loop

    cout.precision(20);
    cout << b << endl << a << endl;
    while(b>a)
    b -= a;
    cout << b << endl << a << endl;

    and see the value of a and b

    Your problem is that the method of not comparing floating
    point values but comparing their difference to a certain limit
    does not work for modulo arithmetic. The reason is simple.

    Assume x(mod y) = 0
    That is, x = yp

    In your case, x and y are floating point values,
    while p is an integer. Since p is an integer, you
    can say x is divisible by y.

    But a computer cannot store floating point numbers exactly.
    so a floating point number x is actually stored as (x+dx)
    or as (x-dx). In your case, 4.5 can be exactly stored, but
    neither can 2.4 or 0.15 . Now consider what happens when you
    divide (x+dx) or (x-dx) by y. (x,y,p > 0)

    (x+dx)(mod y) = dx
    This is ok, your comparison will work in this case, as your
    VERYTINY is > dx

    However, (x-dx)(mod y) = (yp-dx)(mod y)
    = (y(p-1) + y - dx)(mod y) = y-dx
    This y-dx is definitely mmuch greater than your VERYTINY
    and therefore you do not get the desired result.

    I'll give you an example with integers.

    Consider dividing 57 by 19. 57(mod 19) = 0
    58(mod 19) = 1 ( x+dx case)
    56(mod 19) = 18 (x-dx case)

    So you should write
    ( fmod(b,a)<VERYTINY || (a-fmod(b,a))<VERYTINY )

    -Arijit
     
    Arijit, Jul 11, 2004
    #7
  8. Amit Bhatia

    Miguel Guest

    When using floating-point, usually we don't test for equality, instead do
    the kind of test you do (fmod(b, a) > VERYTINY)...
    But if we take a look at the case in particular, the test doesn't fail on my
    machine, and I suspect the > VERYTINY doesn't fail in yours, except for
    negative numbers. That is,

    2.4 can only be finitely represented in binary as 2.3999... that is
    10.0110011(0011)
    0.15 as 0.14(9) (or 0.00100110011(0011))

    in my machine, perhaps yours too, fmod(2.4, 0.15) is exactly 0. This is not
    surprising if we examine the mantissa bits of both numbers, they are equal.

    but 4.5 does have a finite binary representation as 100.1

    but fmod(4.5, 0.15) is only 1.66533e-16, and so is smaller than 1e-10... and
    I don't know why the test should fail....
    Since the case of the denominator being represented exactly implies that a
    multiple is represented exactly too

    So, given best possible representations of the input values the test
    (abs(fmod(b, a)) < VERYTINY)) should work.

    One exception arises when input values are themselves approximations, and,
    in particular, the dividend is slightly less than it would take to be an
    exact multiple. In that case, the remainder will be less than, but very
    close to the denominator. So, we must test the result also against it being
    very close to the denominator.

    So, the full test, that should work for all cases would be (assuming we want
    to know about approximate multiples):

    (abs(fmod(b,a)) < VERYTINY) || (abs(fmod(b,a) - a) < VERYTINY)

    Now, the value you choose for VERYTINY, depends on the application and how
    many operations you have done on the input values. Of course, because the
    result of fmod is in absolute value always less than a, if you know your
    inputs are positive numbers, you can drop both abs function calls.


    Miguel Ramos
     
    Miguel, Jul 11, 2004
    #8
  9. Amit Bhatia

    Miguel Guest


    > What is fmodf? That's not a part of the C or C++ std.
    > libraries. I don't have it on my compiler (DJGPP) either.


    actually fmodf does exist, it is part of the C99 standard, and most modern
    compilers have it.
    but I think we shouldn't be very harsh, it's obvious he meant modf.
     
    Miguel, Jul 11, 2004
    #9
  10. "Miguel" <> wrote in message news:40f18fd8$0$20879$...
    >
    > > What is fmodf? That's not a part of the C or C++ std.
    > > libraries. I don't have it on my compiler (DJGPP) either.

    >
    > actually fmodf does exist, it is part of the C99 standard,


    "fmodf" is a not a keyword in C or C++, nor is it
    a part of their standard libraries, according to my
    reading. I found reference to "fmodf" in the
    documentation for my compiler (DJGPP), where it is
    listed as a "non-ANSI extention to fmod". So unless
    fmodf has been added to the standard libraries very
    recently, it's not standard.

    > and most modern compilers have it.


    Most compilers have lots of added non-ANSI functions.
    Useful, but not standard.

    > it's obvious he meant modf.


    Probably.

    --
    Cheers,
    Robbie Hatley
    Tustin, CA, USA

    http://home.pacbell.net/earnur/
     
    Robbie Hatley, Jul 12, 2004
    #10
  11. On Sun, 11 Jul 2004 20:17:52 -0700, Robbie Hatley <lonewolfintj at pacbell
    dot net> wrote:

    >
    > "Miguel" <> wrote in message
    > news:40f18fd8$0$20879$...
    >>
    >> > What is fmodf? That's not a part of the C or C++ std.
    >> > libraries. I don't have it on my compiler (DJGPP) either.

    >>
    >> actually fmodf does exist, it is part of the C99 standard,

    >
    > "fmodf" is a not a keyword in C or C++, nor is it
    > a part of their standard libraries, according to my
    > reading. I found reference to "fmodf" in the
    > documentation for my compiler (DJGPP), where it is
    > listed as a "non-ANSI extention to fmod". So unless
    > fmodf has been added to the standard libraries very
    > recently, it's not standard.
    >
    >> and most modern compilers have it.

    >
    > Most compilers have lots of added non-ANSI functions.
    > Useful, but not standard.
    >
    >> it's obvious he meant modf.

    >
    > Probably.
    >


    Did you not read Miguel's post? fmodf is defined in the C99 standard,
    section 7.12.10.1. Therefore it is a standard C function. You are talking
    about the older ANSI standard I guess.

    john
     
    John Harrison, Jul 12, 2004
    #11
  12. Amit Bhatia

    P.J. Plauger Guest

    "John Harrison" <> wrote in message
    news:eek:psa0d3euo212331@andronicus...

    > On Sun, 11 Jul 2004 20:17:52 -0700, Robbie Hatley <lonewolfintj at pacbell
    > dot net> wrote:
    >
    > >
    > > "Miguel" <> wrote in message
    > > news:40f18fd8$0$20879$...
    > >>
    > >> > What is fmodf? That's not a part of the C or C++ std.
    > >> > libraries. I don't have it on my compiler (DJGPP) either.
    > >>
    > >> actually fmodf does exist, it is part of the C99 standard,

    > >
    > > "fmodf" is a not a keyword in C or C++, nor is it
    > > a part of their standard libraries, according to my
    > > reading. I found reference to "fmodf" in the
    > > documentation for my compiler (DJGPP), where it is
    > > listed as a "non-ANSI extention to fmod". So unless
    > > fmodf has been added to the standard libraries very
    > > recently, it's not standard.
    > >
    > >> and most modern compilers have it.

    > >
    > > Most compilers have lots of added non-ANSI functions.
    > > Useful, but not standard.
    > >
    > >> it's obvious he meant modf.

    > >
    > > Probably.
    > >

    >
    > Did you not read Miguel's post? fmodf is defined in the C99 standard,
    > section 7.12.10.1. Therefore it is a standard C function. You are talking
    > about the older ANSI standard I guess.


    Even C89 provided for *f and *l versions of the standard math functions.
    They were permitted but not required. So fmodf has been around for a
    long time. None of which alters the fact that it *still* probably
    should have been modf in the posting.

    P.J. Plauger
    Dinkumware, Ltd.
    http://www.dinkumware.com
     
    P.J. Plauger, Jul 12, 2004
    #12
  13. Amit Bhatia

    Amit Bhatia Guest

    Guys,
    I was indeed using fmodf and fmod: I use g++ version 3.2 on rh 9.0 (with
    -ansi compilation flag) to find the remainder when two double precision
    values are divided one of which is exact multiple of the other.
    thanks, for pointing me out that it is not exactly computable and I need to
    be a bit careful while doing this stuff. ;) Anyway, I am using a slightly
    different check now which was suggested by Arijit and which works well.

    thanks,
    amit.
     
    Amit Bhatia, Jul 12, 2004
    #13
  14. John Harrison chastised me thusly:

    > Did you not read Miguel's post?


    Oh, I read it; I just didn't believe it, because the
    books available to me said otherwise.

    > fmodf is defined in the C99 standard, section
    > 7.12.10.1. Therefore it is a standard C function.


    Quoting section numbers on my ass, eh? :)

    > You are talking about the older ANSI standard I guess.


    Yes, I suppose my books are all based on C90, not C99.

    I see you're going to throw the book at me, so I'd
    better get this standard you guys keep talking about.

    ::: gets standard :::

    Now, let me see... Yes, here we go...

    Pursuant to ISO/IEC 9899:1999, §7.12.10.1, paragraph 1,
    the header math.h shall contain:

    double fmod (double x, double y)
    float fmodf (float x, float y)
    long double fmodl (long double x, long double y)

    OK, it seems that you guys were right.

    But wait, that's the C standard, not C++.

    Pursuant to ISO/IEC 14882, §26.5, paragraph 6, I see
    that in standard C++, the <cmath> header includes:

    double fmod (double x, double y)
    float fmod (float x, float y)
    long double fmod (long double x, long double y)

    Uses overloaded versions of fmod, instead of fmodf and
    fmodl.

    §26.5, paragraph 2 does say "the contents of these
    headers (<cmath> and <cstdlib>) are the same as the C
    Standard Library headers math.h and stdlib.h, with the
    following additions...", which would seem to imply that
    fmodf, fmodl, and many other such library functions
    are a part of standard C++. But then, 14882 was
    written in 1998, so "Standard C" actually meant C90,
    so one could argue that fmodf, fmodl, etc. are therefore
    NOT part of standard C++. So perhaps I was right, after
    all. :)

    --
    Feeling argumentative,
    Robbie Hatley
    Tustin, CA, USA
    email: lonewolfintj at pacbell dot net
    web: home dot pacbell dot net slant earnur slant
     
    Robbie Hatley, Jul 14, 2004
    #14
  15. Amit Bhatia

    P.J. Plauger Guest

    "Robbie Hatley" <lonewolfintj at pacbell dot net> wrote in message
    news:40f4c36d$1_2@127.0.0.1...

    > Pursuant to ISO/IEC 9899:1999, §7.12.10.1, paragraph 1,
    > the header math.h shall contain:
    >
    > double fmod (double x, double y)
    > float fmodf (float x, float y)
    > long double fmodl (long double x, long double y)
    >
    > OK, it seems that you guys were right.
    >
    > But wait, that's the C standard, not C++.
    >
    > Pursuant to ISO/IEC 14882, §26.5, paragraph 6, I see
    > that in standard C++, the <cmath> header includes:
    >
    > double fmod (double x, double y)
    > float fmod (float x, float y)
    > long double fmod (long double x, long double y)
    >
    > Uses overloaded versions of fmod, instead of fmodf and
    > fmodl.
    >
    > §26.5, paragraph 2 does say "the contents of these
    > headers (<cmath> and <cstdlib>) are the same as the C
    > Standard Library headers math.h and stdlib.h, with the
    > following additions...", which would seem to imply that
    > fmodf, fmodl, and many other such library functions
    > are a part of standard C++. But then, 14882 was
    > written in 1998, so "Standard C" actually meant C90,
    > so one could argue that fmodf, fmodl, etc. are therefore
    > NOT part of standard C++. So perhaps I was right, after
    > all. :)


    Except that you aren't. The float and long double math
    functions that are optional in C90 are explicitly required
    in C++98.

    P.J. Plauger
    Dinkumware, Ltd.
    http://www.dinkumware.com
     
    P.J. Plauger, Jul 14, 2004
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Amit Bhatia

    Floating point arithmetic.

    Amit Bhatia, Jul 11, 2004, in forum: C Programming
    Replies:
    5
    Views:
    317
    Christian Bau
    Jul 18, 2004
  2. Shawn
    Replies:
    11
    Views:
    559
    Gregory Pietsch
    Jul 21, 2004
  3. Satpreet
    Replies:
    1
    Views:
    477
    Michael Mair
    Feb 27, 2006
  4. Robert Dodier
    Replies:
    1
    Views:
    409
    Twisted
    Jul 31, 2007
  5. Saraswati lakki
    Replies:
    0
    Views:
    1,341
    Saraswati lakki
    Jan 6, 2012
Loading...

Share This Page