#define EPSILON 0.000001
#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)))
Now for checking if two doubles, say x and y, are close we use eq(a,b)
<= EPSILON
>#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
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
> 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 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.
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
I don't know. You can do both if you want.
/* BEGIN new.c output */
(&*max)(1.0, -1.1) is 1.000000
reldiff(1.0, -1.1) is 1.909091
/* END new.c output */
/* BEGIN new.c */
#include<stdio.h>
#include "reldiff.h"
int main(void)
{
puts("/* BEGIN new.c output */\n");
printf("(&*max)(1.0, -1.1) is %f\n",
(&*max)(1.0, -1.1));
printf("reldiff(1.0, -1.1) is %f\n",
reldiff(1.0, -1.1));
puts("\n/* END new.c output */");
return 0;
}
/* END new.c */
/* BEGIN reldiff.h */
#ifndef H_RELDIFF_H
#define H_RELDIFF_H
#define max(x, y) ((x) > (y) ? (x) : (y))
double (max)(double x, double y);
double reldiff(double x, double y);
#endif
/* END reldiff.h */
/* BEGIN reldiff.c */
#include <math.h>
#include "reldiff.h"
double (max)(double x, double y)
{
return max(x, y);
}
double reldiff(double x, double y)
{
return fabs(x - y) / max(fabs(x), fabs(y));
}
/* END reldiff.c */
--
pete
> Ben Bacarisse wrote:
>> August Karlstrom <fusio...@comhem.se> 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.
>On Jun 29, 7:17 pm, August Karlstrom <fusionf...@comhem.se> 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
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.
can you get almost-divide-by-ero if a and b are very small?
For instance what if
a == b == 1e-53 (or some other very non-zero number)
--
Nick Keighley
On 22 Jul, 15:52, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
> On 29 Jun, 12:29, pereges <Brol...@gmail.com> 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 EPSILON 0.000001
> > #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)))
>
> > Now for checking if two doubles, say x and y, are close we use eq(a,b)
> > <= EPSILON
>
> can you get almost-divide-by-[z]ero if a and b are very small?
> For instance what if
> a == b == 1e-53 (or some other very [small] non-zero number)
>
> --Nick Keighley
--
Nick Keighley
Just use Knuth's fcmp(). It accounts for a number of subtle issues,
which are (nearly) impossible to capture in a simple macro.
Download it from
http://fcmp.sourceforge.net/
~Glynne