Writing a macro for checking close enough floating points.

Discussion in 'C Programming' started by pereges, Jun 29, 2008.

  1. pereges

    pereges Guest

    Hi, I'm trying to write a macro for the relative difference function
    which is used to check the close enough floating point values. Is
    this correct way to write it ? :


    #define max(x, y) ((x) > (y) ? (x) : (y))
    #define eq(a, b) max(fabs(a), fabs(b)) == 0.0 ? 0.0 : fabs(a - b) /
    (max(fabs(a), fabs(b)))
    pereges, Jun 29, 2008
    #1
    1. Advertising

  2. In article <>,
    pereges <> wrote:
    >Hi, I'm trying to write a macro for the relative difference function
    >which is used to check the close enough floating point values. Is
    >this correct way to write it ? :


    >#define max(x, y) ((x) > (y) ? (x) : (y))
    >#define eq(a, b) max(fabs(a), fabs(b)) == 0.0 ? 0.0 : fabs(a - b) /
    >(max(fabs(a), fabs(b)))


    The name eq() suggests a logical test. Logical tests in C return
    an integral 0 or an integral 1. Your macro returns a floating 0.0
    or some other floating point calculation (which might be floating 0.0
    if the two values are equal but non-0.) Using a logical name for a test
    but returning a floating point value suggests that you have some
    confusion about how this macro is going to be used.

    Also, consider that in the eq() macro that the arguments might be
    expressions. Unless subtraction is the lowest precedence operator
    (and it isn't), fabs(a - b) is not going to be correct if a or b
    are expressions of lower precedence. Take the hint from the way that
    the x and y arguments are used in max().

    I have not attempted a numeric analysis to determine what
    value your eq() macro returns.
    --
    "The quirks and arbitrariness we observe force us to the
    conclusion that ours is not the only universe." -- Walter Kistler
    Walter Roberson, Jun 29, 2008
    #2
    1. Advertising

  3. pereges wrote:
    > Hi, I'm trying to write a macro for the relative difference function
    > which is used to check the close enough floating point values. Is
    > this correct way to write it ? :
    >
    >
    > #define max(x, y) ((x) > (y) ? (x) : (y))
    > #define eq(a, b) max(fabs(a), fabs(b)) == 0.0 ? 0.0 : fabs(a - b) /
    > (max(fabs(a), fabs(b)))


    Are you sure you really need to define the functions as macros? If you
    define them as ordinary functions they can typically be inlined by the
    compiler anyway. This way you will also have type safety. I would write
    something like the following:

    #include <assert.h>
    #include <math.h>

    double max(double x, double y)
    {
    return (x > y)? x: y;
    }


    double reldiff(double x, double y)
    {
    assert((x != 0) || (y != 0));

    return fabs(x - y) / max(fabs(x), fabs(y));
    }


    August
    August Karlstrom, Jun 29, 2008
    #3
  4. pereges

    pereges Guest

    On Jun 29, 7:17 pm, August Karlstrom <> wrote:


    > Are you sure you really need to define the functions as macros? If you
    > define them as ordinary functions they can typically be inlined by the
    > compiler anyway. This way you will also have type safety. I would write
    > something like the following:
    >
    > #include <assert.h>
    > #include <math.h>
    >
    > double max(double x, double y)
    > {
    > return (x > y)? x: y;
    >
    > }
    >
    > double reldiff(double x, double y)
    > {
    > assert((x != 0) || (y != 0));
    >
    > return fabs(x - y) / max(fabs(x), fabs(y));
    >
    > }


    Is it always better to write functions over macros for even smaller
    things, say square of a number ?
    For my project, I have a file called util.h which basically contains
    some math macros like this, error display macro, constants etc. all at
    one place and its a few lines anyway so including it in most files
    won't hurt that bad whereas if i write full fledge functions it
    increases the amount of code that is included everytime. Is that
    correct ?
    pereges, Jun 29, 2008
    #4
  5. August Karlstrom <> writes:

    > pereges wrote:
    >> Hi, I'm trying to write a macro for the relative difference function

    <snip>
    > ... I would
    > write something like the following:
    >
    > #include <assert.h>
    > #include <math.h>
    >
    > double max(double x, double y)
    > {
    > return (x > y)? x: y;
    > }
    >
    >
    > double reldiff(double x, double y)
    > {
    > assert((x != 0) || (y != 0));


    What is this assert for? What problem is caused by x == 0 && y == 0?
    Did you intend to check that

    assert(max(fabs(x), fabs(y)) != 0);

    ? If so, i would argue that this is not a good use of assert. Not
    unless you know something about the use of this function that makes
    calling it in that way a logic fault in the program.

    > return fabs(x - y) / max(fabs(x), fabs(y));
    > }


    --
    Ben.
    Ben Bacarisse, Jun 29, 2008
    #5
  6. Ben Bacarisse wrote:
    > August Karlstrom <> writes:
    >>
    >> double reldiff(double x, double y)
    >> {
    >> assert((x != 0) || (y != 0));

    >
    > What is this assert for? What problem is caused by x == 0 && y == 0?


    Division by zero (mathematically speaking).

    > Did you intend to check that
    >
    > assert(max(fabs(x), fabs(y)) != 0);


    Yes, same thing.

    > ? If so, i would argue that this is not a good use of assert. Not
    > unless you know something about the use of this function that makes
    > calling it in that way a logic fault in the program.


    The relative difference of x and y is undefined if both x and y are
    zero. The assert statement is used here to put constraints on the input
    parameters (for debugging purposes and for documentation). The caller
    must of course make sure that this precondition is met.


    August
    August Karlstrom, Jun 29, 2008
    #6
  7. August Karlstrom <> writes:

    > Ben Bacarisse wrote:
    >> August Karlstrom <> writes:
    >>>
    >>> double reldiff(double x, double y)
    >>> {
    >>> assert((x != 0) || (y != 0));

    >>
    >> What is this assert for? What problem is caused by x == 0 && y == 0?

    >
    > Division by zero (mathematically speaking).
    >
    >> Did you intend to check that
    >>
    >> assert(max(fabs(x), fabs(y)) != 0);

    >
    > Yes, same thing.


    Duh! I forgot the fabs()s were there (despite having typed them).

    --
    Ben.
    Ben Bacarisse, Jun 29, 2008
    #7
  8. On Sun, 29 Jun 2008 07:57:08 -0700 (PDT), pereges <>
    wrote:

    >On Jun 29, 7:17 pm, August Karlstrom <> wrote:
    >
    >
    >> Are you sure you really need to define the functions as macros? If you
    >> define them as ordinary functions they can typically be inlined by the
    >> compiler anyway. This way you will also have type safety. I would write
    >> something like the following:
    >>
    >> #include <assert.h>
    >> #include <math.h>
    >>
    >> double max(double x, double y)
    >> {
    >> return (x > y)? x: y;
    >>
    >> }
    >>
    >> double reldiff(double x, double y)
    >> {
    >> assert((x != 0) || (y != 0));
    >>
    >> return fabs(x - y) / max(fabs(x), fabs(y));
    >>
    >> }

    >
    >Is it always better to write functions over macros for even smaller
    >things, say square of a number ?


    It is always better to write the code in a way that best (tm)
    satisfies several possibly competing requirements.

    First and foremost, it must do the job.
    It should be easily maintained.
    It should be easy to read and understand
    It should be extendable (for example, can the "arguments" be
    expressions with side effects).
    It should promote re-use.

    >For my project, I have a file called util.h which basically contains
    >some math macros like this, error display macro, constants etc. all at
    >one place and its a few lines anyway so including it in most files
    >won't hurt that bad whereas if i write full fledge functions it


    A lot of projects are done this way so it can't be that unreasonable.

    >increases the amount of code that is included everytime. Is that
    >correct ?


    If you invoke a macro 100 times will it generate more code than if you
    call the same function 100 times? As always, it depends.

    If you find a problem with the macro, how many routines will need to
    be recompiled? If you fix the function, how many?

    You are on the verge of treating the issue as a premature
    optimization. In the vast majority of cases, this places the emphasis
    on the wrong syllable. Write clear working code and don't worry about
    extra lines of code in the compile phase or a few extra K of memory in
    the execution phase.


    Remove del for email
    Barry Schwarz, Jun 29, 2008
    #8
  9. pereges

    Flash Gordon Guest

    August Karlstrom wrote, On 29/06/08 16:40:
    > Ben Bacarisse wrote:
    >> August Karlstrom <> writes:
    >>>
    >>> double reldiff(double x, double y)
    >>> {
    >>> assert((x != 0) || (y != 0));

    >>
    >> What is this assert for? What problem is caused by x == 0 && y == 0?

    >
    > Division by zero (mathematically speaking).


    Logically it would more more sense to do
    if (x==0 && y==0) return 0;
    After all, if most numbers are identical (i.e. 0) there is no difference!

    Alternatively, reduce the above to one test with:
    if (x==y) return 0;

    >> Did you intend to check that
    >>
    >> assert(max(fabs(x), fabs(y)) != 0);

    >
    > Yes, same thing.
    >
    >> ? If so, i would argue that this is not a good use of assert. Not
    >> unless you know something about the use of this function that makes
    >> calling it in that way a logic fault in the program.

    >
    > The relative difference of x and y is undefined if both x and y are
    > zero. The assert statement is used here to put constraints on the input
    > parameters (for debugging purposes and for documentation). The caller
    > must of course make sure that this precondition is met.


    Since this function is for use in determining if two numbers are
    identical such a restriction would not be sensible. Return 0 which is a
    sensible definition for the relative difference if both number are 0
    since the absolute difference is 0!
    --
    Flash Gordon
    Talking about nothing.
    Flash Gordon, Jul 22, 2008
    #9
    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. Anders K. Jacobsen [DK]

    Problem with floating points in datagrid

    Anders K. Jacobsen [DK], Apr 7, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    313
    Karl Seguin
    Apr 7, 2005
  2. =?Utf-8?B?bWF2cmlja18xMDE=?=

    is Connection.close() enough or

    =?Utf-8?B?bWF2cmlja18xMDE=?=, Jun 27, 2006, in forum: ASP .Net
    Replies:
    6
    Views:
    3,923
    =?Utf-8?B?bWF2cmlja18xMDE=?=
    Jun 28, 2006
  3. pereges
    Replies:
    7
    Views:
    317
    Barry Schwarz
    May 31, 2008
  4. pereges
    Replies:
    3
    Views:
    342
    ~Glynne
    Jul 23, 2008
  5. Iñaki Baz Castillo
    Replies:
    7
    Views:
    819
    Iñaki Baz Castillo
    Jan 12, 2010
Loading...

Share This Page