problem incrementing my variable

U

user923005

Bartc said:
user923005 wrote: [...]
Maybe something like this:
#include <float.h>
#include <math.h>
/* 'Close enough' comparison: */
int double_compare(double d1, double d2)
{
    if (d1 > d2)
        if ((d1 - d2) < fabs(d1 * DBL_EPSILON))
DBL_EPSILON is the smallest possible step for a floating point value? Within
the context of CAD, I would use a tolerance perhaps a million times bigger.
At least.

DBL_EPSILON is "the difference between 1 and the least value greater
than 1 that is representable in the given floating point type" (double
in this case).  The actual smallest step varies tremendously depending
on the magnitude of the value -- which is why it's called *floating*
point.  DBL_EPSILON is far too coarse for values near zero, and
unrepresentably fine for large values.

I haven't used fuzzy floating-point equality comparisons very often,
but it seems to me that the problem is more difficult problem than the
way it's usually presented.  You need to ask yourself just what it
means for two values to be "equal", and how the values you're trying
to compare were computed; the latter can affect how much of the
difference is real, and how much is due to rounding errors.  Both of
these things can vary greatly depending on the application.  It's not
just about comparing numbers; you have to understand what they *mean*.

You will notice that I have scaled the delta to DBL_EPSILON mulitplied
by the magnitude of the largest value.
Further, this scaled value is compared to the difference and not to
either value.
Of course, it is possible that a larger tolerance is fine, in which
case a larger value could be substituted.
 
U

user923005

I missed the fact that DBL_EPSILON is scaled before use.

Even so, using a value a million times bigger means that on a line 1000km
long (from the origin), a point needs to be within 0.2mm to be considered on
the line.

The sample code is for differences that are both mathematically and
numerically discernable.

It is possible that 'pixel' resolution or some such is what is really
wanted. Only the OP will know that since it is not stated.
 
G

Gary

The sample code is for differences that are both mathematically and
numerically discernable.

You guys are good, this is a ton of great stuff. Thanks.
It is possible that 'pixel' resolution or some such is what is really
wanted.  Only the OP will know that since it is not stated.

I will try to stately it correctly, but my terms may be used
improperly. My interest deals with a geometric shape that is
rectilinear, and whose vertices's are always right angles. I want to
look at each edge of the polygon that is determined by two ordered
pairs. I then have a path that I want to check if one of its segments
crosses this edge. Each path segment is also defined by two ordered
pairs. If easier I can assume that one of the paths endpoint must be
exactly on the line, (but it is prefer not too, and just has to cross
it), and then find the intersection. Fortunately, I don't have to deal
with anything by 90 degree angles. The resolution of the points is on
a .005 micron grid.
 
B

Bartc

Gary said:
Arg.... anything BUT 90 degrees. All angles are 90 degrees only.

How about the path segments, are they also at 90 degrees? (Beginning to
sound like an Etch-a-sketch..)

This comes down to checking whether one segment of your path (maybe vertical
or horizontal or possibly any orientation), crosses any edge of your shape
(vertical or horizontal).

This is fairly straightforward, just look out for the usual pitfalls such as
the segment crossing a vertex (piercing the shape or being tangential),
crossing more than one edge, or is parallel to and coincident with an edge,
etc. As well as deciding what tolerances to use.

(I'm not sure I would solve it by incrementally traversing the segment until
it hits an edge, you can uses maths to find the intersection, with further
checks as to whether that point is both on the segment and the edge.)

This is no longer much of a C problem, but come back here for any coding
issues.
 
C

CBFalconer

Ian said:
Isn't that taken care of by default argument promotion?

No, because printf doesn't know anything about the actual argument
presented. Its only identification is in the format string, which
doesn't have to be fixed. You can construct that format string
just before calling printf, for example. printf assumes arguments
have been promoted, but nothing does any promotion.

Actually, for this sort of problem, I would recommend using integer
arguments where possible. i.e.:

int foo(float begin, float increment, int times) {
int i;

for (i = 0; i < times; i++)
printf("%f\n", (double) (begin + i * increment));
} /* foo */

and you can do things like passing in the desired format:

int foo(float begin, float increment, int times, char *format) {
int i;

for (i = 0; i < times; i++)
printf(format, (double) (begin + i * increment));
fflush(stdin);
} /* foo */
 
K

Keith Thompson

CBFalconer said:
No, because printf doesn't know anything about the actual argument
presented. Its only identification is in the format string, which
doesn't have to be fixed. You can construct that format string
just before calling printf, for example. printf assumes arguments
have been promoted, but nothing does any promotion.
[...]

You are mistaken. This:

float f = 42.0;
printf("f = %f\n", f);

is perfectly correct code. The value of is is promoted, by the
default argument promotions, from float to double, which matches the
"%f" format. The default argument promotions include both the integer
promotions and promotion from float to double. See C99 6.5.2.2p6-7.
 
B

Bartc

Keith Thompson said:
CBFalconer said:
No, because printf doesn't know anything about the actual argument
presented. Its only identification is in the format string, which
doesn't have to be fixed. You can construct that format string
just before calling printf, for example. printf assumes arguments
have been promoted, but nothing does any promotion.
[...]

You are mistaken. This:

float f = 42.0;
printf("f = %f\n", f);

is perfectly correct code. The value of is is promoted, by the
default argument promotions, from float to double, which matches the
"%f" format. The default argument promotions include both the integer
promotions and promotion from float to double. See C99 6.5.2.2p6-7.

CBF might have a point, at least when int/double conversions are involved.
This:

printf(s,i);

where i is an integer, and s *might* contain %d or %f, could cause a problem
I think.
 
K

Keith Thompson

Bartc said:
Keith Thompson said:
CBFalconer said:
Ian Collins wrote:
CBFalconer wrote:

Note that printf expects to receive a double. You should so cast
the argument. This is one of the few places that a C cast is
needed.

Isn't that taken care of by default argument promotion?

No, because printf doesn't know anything about the actual argument
presented. Its only identification is in the format string, which
doesn't have to be fixed. You can construct that format string
just before calling printf, for example. printf assumes arguments
have been promoted, but nothing does any promotion.
[...]

You are mistaken. This:

float f = 42.0;
printf("f = %f\n", f);

is perfectly correct code. The value of is is promoted, by the
default argument promotions, from float to double, which matches the
"%f" format. The default argument promotions include both the integer
promotions and promotion from float to double. See C99 6.5.2.2p6-7.

CBF might have a point, at least when int/double conversions are
involved. This:

printf(s,i);

where i is an integer, and s *might* contain %d or %f, could cause a
problem I think.

Of course, and casting the argument doesn't solve that problem. The
value of the format string can be determined at run time (though it's
very commonly a string literal), but the types of the following
arguments are determined when you write the code. And a float
argument in that context will always be promoted to double (which is
why there's no printf format for float).
 
B

Bartc

Keith Thompson said:
Of course, and casting the argument doesn't solve that problem. The
value of the format string can be determined at run time (though it's
very commonly a string literal), but the types of the following
arguments are determined when you write the code.

I meant when the programmer knows what % codes (and how many?), are in the
format string, but not the compiler. If neither know, then I don't think
that's workable.
 
J

jameskuyper

CBFalconer said:
No, because printf doesn't know anything about the actual argument
presented. Its only identification is in the format string, which
doesn't have to be fixed. You can construct that format string
just before calling printf, for example. printf assumes arguments
have been promoted, but nothing does any promotion.

6.5.2.2.p7 says:

"The ellipsis notation in a function prototype declarator causes
argument type conversion to stop after the last declared parameter.
The default argument promotions are performed on trailing arguments."

The code in question was:
float p;
for ( p = 0; p <= 1; p = p + .005) {
printf("p value is %f\n", p);

In this case, the last declared parameter is the format string, on
which argument type conversions are performed. 'p', on the other hand,
is the only trailing argument, on which default argument promotions
are performed.
 
U

user923005

You guys are good, this is a ton of great stuff. Thanks.


I will try to stately it correctly, but my terms may be used
improperly. My interest deals with a geometric shape that is
rectilinear, and whose vertices's are always right angles. I want to
look at each edge of the polygon that is determined by two ordered
pairs. I then have a path that I want to check if one of its segments
crosses this edge. Each path segment is also defined by two ordered
pairs. If easier I can assume that one of the paths endpoint must be
exactly on the line, (but it is prefer not too, and just has to cross
it), and then find the intersection. Fortunately, I don't have to deal
with anything by 90 degree angles. The resolution of the points is on
a .005 micron grid.

Since your questions are not C questions per se, may I suggest
or
Your problem is an intersection problem. Dave Eberly has a nice site
with lots of software for that sort of calculation.
I have several of his books. I recommend that you buy one and read it
because then this sort of problem will be second nature for you to
solve.
I have "Game Physics" and "Geometric Tools":
http://www.geometrictools.com/Books/Books.html

The relevant code for intersection is:
http://www.geometrictools.com/LibFoundation/Intersection/Intersection.html
In particular, I suggest that you examine:
"Intersection of rectangles (2D) or boxes (3D)."
 
K

Keith Thompson

Bartc said:
I meant when the programmer knows what % codes (and how many?), are in
the format string, but not the compiler. If neither know, then I don't
think that's workable.

The fact that the format string might not be known at compile time
doesn't cause any special problems. If you pass an argument of type
int, and it comes after the format string argument, then it will be
passed as type int. If you pass an argument of type float, it will be
passed as double.

Just what kind of problem did you have in mind?
 
B

Bartc

Keith Thompson said:
The fact that the format string might not be known at compile time
doesn't cause any special problems. If you pass an argument of type
int, and it comes after the format string argument, then it will be
passed as type int. If you pass an argument of type float, it will be
passed as double.

Just what kind of problem did you have in mind?

Each parameter of printf() after the first, should match the corect %-code
in the format string. With a runtime format string these might not be known:

printf(s,"ABC",123,3.14);

If s contains "...%f... %s...%d..." the results might be unexpected. So a
runtime format string is only workable with knowledge of the %-codes (but
not quite enough knowledge to just use a literal instead).
 
C

CBFalconer

Keith said:
CBFalconer said:
No, because printf doesn't know anything about the actual argument
presented. Its only identification is in the format string, which
doesn't have to be fixed. You can construct that format string
just before calling printf, for example. printf assumes arguments
have been promoted, but nothing does any promotion.
[...]

You are mistaken. This:

float f = 42.0;
printf("f = %f\n", f);

is perfectly correct code. The value of is is promoted, by the
default argument promotions, from float to double, which matches the
"%f" format. The default argument promotions include both the integer
promotions and promotion from float to double. See C99 6.5.2.2p6-7.

I do seem to have something mixed up. However what about:

long l = 42;
printf("%d\n", l);
or
int i = 42;
printf("%ld\n", i);

which WILL need the cast. Also, the %d isn't fixed, because the
format string need not be a constant.
 
K

Keith Thompson

Bartc said:
Each parameter of printf() after the first, should match the corect
%-code in the format string. With a runtime format string these might
not be known:

printf(s,"ABC",123,3.14);

If s contains "...%f... %s...%d..." the results might be
unexpected. So a runtime format string is only workable with knowledge
of the %-codes (but not quite enough knowledge to just use a literal
instead).

The number and types of arguments following the format string
(matching the ", ...") is fixed when the program is written. So the
the format string, even if it's generated at run-time, *must* specify
exactly the same sequence of argument types as what's actually passed
(if the call is actually executed). As is often the case with printf,
it's entirely up to the programmer to get this right.
 
J

J. J. Farrell

Bartc said:
Keith Thompson said:
CBFalconer said:
Ian Collins wrote:
CBFalconer wrote:

Note that printf expects to receive a double. You should so cast
the argument. This is one of the few places that a C cast is
needed.

Isn't that taken care of by default argument promotion?

No, because printf doesn't know anything about the actual argument
presented. Its only identification is in the format string, which
doesn't have to be fixed. You can construct that format string
just before calling printf, for example. printf assumes arguments
have been promoted, but nothing does any promotion.
[...]

You are mistaken. This:

float f = 42.0;
printf("f = %f\n", f);

is perfectly correct code. The value of is is promoted, by the
default argument promotions, from float to double, which matches the
"%f" format. The default argument promotions include both the integer
promotions and promotion from float to double. See C99 6.5.2.2p6-7.

CBF might have a point, at least when int/double conversions are
involved. This:

printf(s,i);

where i is an integer, and s *might* contain %d or %f, could cause a
problem I think.

The programmer obviously has to make sure that the argument is of the
type which he's told printf() to expect. If he's told it to expect a
double by using %f, then he can give a double, or a float (which will be
automatically converted to a double), or something cast to a double, or
something cast to a float (which will then be automatically converted to
a double), or any other expression which results in a float or a double.

If, at the time of writing the code, he doesn't know whether printf()
will be using %f or %d at run-time, then he's stuffed - no casting of
the argument will be correct for both cases.
 
K

Keith Thompson

CBFalconer said:
I do seem to have something mixed up. However what about:

long l = 42;
printf("%d\n", l);
or
int i = 42;
printf("%ld\n", i);

which WILL need the cast.

Certainly. "l" and "i" are passed as long and int, respectively, so
both printf calls are incorrect (invoke undefine behavior). Though in
both cases, a better solution would be to fix the format string:

long l = 42;
printf("%ld\n", l);

int i = 42;
printf("%d\n", i);

Unless the format string is computed at run time and imposed by
something that's outside the programmer's control.
Also, the %d isn't fixed, because the
format string need not be a constant.

But given this:

int i = 42;
printf(fmt, i);

fmt *must* consume one argument of type int. If it doesn't, the
behavior is undefined. If you happen to know that the format string
consumes one argument of type long, I suppose you could write:

int i = 42;
printf(fmt, (long)i);

but I can't think if any plausible scenario where that would actually
happen.

Casts are commonly required for arguments to printf, but usually when
there's no built-in format for the type you're passing. The classic
pre-C99 example is:

printf("sizeof x = %lu\n", (unsigned long)sizeof x);

though of course C99 has "%zu".
 
N

Nate Eldredge

Keith Thompson said:
But given this:

int i = 42;
printf(fmt, i);

fmt *must* consume one argument of type int. If it doesn't, the
behavior is undefined.

Nitpick: it could also consume no arguments at all. If fmt is the
string "Hello, world", the code is fine and doesn't invoke any undefined
behavior; the second argument will be evaluated but ignored.

7.19.6.1 (2).
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top