Pseudo code to C help needed

P

Phil Carmody

Ken Brody said:
I've got a pdf file with some pseudo code that seems to have been written
by someone familiar with C++. I'm implementing the code in C, but need
help translating one particular line:

const int imax = 2*std::numeric_limits<Real>::max_exponent;

Can someone explain this and give me an equivalent C line of code? It
then iterates through a loop imax times.
[...]

You might get a better answer in comp.lang.c++ as to what that statement
means. However, a quick search for
std::numeric_limits said:
The value of std::numeric_limits<T>::max_exponent is the largest positive
number n such that 10^(n-1) is a representable finite value of the
floating-point type T.

which I shall call reference 1.
And this page gives a chart of #defines:

http://en.cppreference.com/w/cpp/types/numeric_limits/max_exponent

My guess is that it is the equivalent of:

const int imax = 2*(LDBL_MAX_EXP);

(I guess it depends on what type "Real" is.)


Strangely, your logic doesn't hold, yet you've got to the right answer!

Reference 1 is *surely* in error. I believe[*] that the quote
describes something closer (but an out-by-one out) to
std::numeric_limits<T>::max_exponent10
where the "10" part is key. Were reference 1 to be absolutely
correct, then the answer would be (modulo out-by-ones):
imax = 2 * {FLT,DBL,LDBL}_MAX_10_EXP depending on what "Real" is.

Fortunately, you blasted past that presumed copy-pasto, and reached
what is almost certainly the right answer.

However, given that C++ is C++[*], it's possible that imax is used
in ways that aren't C-compatible (being as it is a const variable,
rather than a constant), and something bizarre like:
enum { imax = 2*DBL_MAX_EXP };
might be necessary to achieve all the constanty goodness that C++
may[*] provide.

Phil
[* I know bugger all about C++, or at least that's what I claim in public.]
 
G

glen herrmannsfeldt

(snip, I wrote)
The description of std::numeric_limits<T>::max_exponent in the C++
standard is almost an exact match for the description of the *_MAX_EXP
macros in the C standard. If Real is a typedef for float, which appears
to be the case, why would you use anything other than FLT_MAX_EXP as a C
replacement for that C++ expression? What advantage do you see from the
use of 7*FLT_MAX_10_EXP instead? I see one substantial disadvantage: if
FLT_MAX_EXP is not an exact multiple of 7 (and in general, it won't be),
then 7*FLT_MAX_10_EXP cannot have the same value as FLT_MAX_EXP. Can you
come up with any advantage to make up for that disadvantage?

The OP wants to use it as part of a convergence test for an
iterative approximation to guard against infinite loops.

Normally there will be a test that exits the loop early, but even
if there isn't, a few extra iterations isn't so bad.

The number of iterations often depends on how far you are from
the right answer, which can scale with exponent size.

Note that FLT_MAX_EXP does not properly scale if the base
can be different, but FLT_MAX_10_EXP does.

-- glen
 
M

Mark Storkamp

glen herrmannsfeldt said:
(snip, I wrote)


The OP wants to use it as part of a convergence test for an
iterative approximation to guard against infinite loops.

That's correct.
Normally there will be a test that exits the loop early, but even
if there isn't, a few extra iterations isn't so bad.

Two tests, actually. But there are typically as many as 900,000 points
being tested, so a few extra iterations may add up over time.
The number of iterations often depends on how far you are from
the right answer, which can scale with exponent size.

Note that FLT_MAX_EXP does not properly scale if the base
can be different, but FLT_MAX_10_EXP does.

And here you lost me, but I now plan on running two versions, one with
each constant, and seeing how much, if any, difference there is in the
results. My raw data is coming from a 3D scanner via an .stl file, so as
long as my results are accurate to within .001" I'll be okay. Anything
else is just noise anyway.
 
M

Mark Storkamp

Keith Thompson said:
Why are you using floats rather than doubles? double tends to be the
"default" floating-point type in C.

The raw data is coming from a 3D scan via an .stl file, so the data is
coming in as floats, all values are less than 20", and resolution less
than .001" is just noise. When I first started writing this program I
didn't see any point in converting it to double. Now that the project
has grown way beyond what I had imagined it to ever be, and I'm doing a
whole lot more manipulation on the data, it's probably too late to
change things now, even if it were slightly more efficient.
 
J

James Kuyper

(snip, I wrote)


The OP wants to use it as part of a convergence test for an
iterative approximation to guard against infinite loops.

The value of max_exponent is entirely irrelevant to that usage. If
that's what was being done, the limit should have been expressed in
terms of std::numeric_limits<Real>::epsilon. With Real a typedef for
float, that corresponds to FLT_EPSILON.

It's not exactly impossible that max_exponent is being misused in this
way - but without seeing the details of the actual code, we can't be
sure that it is. It's impolite to the writer of the pseudo-code to just
assume that he is misusing it without know precisely how he used it.

There's a simple check that the OP could perform: properly written C++
code that makes use of std::numeric_limits<Real>::max_epsilon should, in
general, use std::numeric_limits<Real>::radix in close association with
max_epsilon. Improperly written code will assume that radix==2, and will
get away with that assumption most of the time. In that case,
translating it as 7*FLT_MAX_10_EXP, as you suggest, would be safer on
machines where FLT_RADIX!=2. However, the right fix is to replace 2 with
FLT_RADIX, or 0.5 with 1/FLT_RADIX, wherever appropriate.
 
G

glen herrmannsfeldt

Mark Storkamp said:
That's correct.
Two tests, actually. But there are typically as many as 900,000 points
being tested, so a few extra iterations may add up over time.

It would have been convenient if they also supplied FLT_MAX_2_EXP.
And here you lost me, but I now plan on running two versions, one with
each constant, and seeing how much, if any, difference there is in the
results. My raw data is coming from a 3D scanner via an .stl file, so as
long as my results are accurate to within .001" I'll be okay. Anything
else is just noise anyway.

My guess is that this is a last resort test, but that could be wrong.

The problem is that FLT_MAX_EXP depends on FLT_RADIX. Unless you
are taking the bits apart, any tests that use FLT_MAX_EXP should
also use FLT_RADIX, but that isn't so convenient in this case.

I believe they are preprocessor symbols, so you could:

#if FLT_RADIX!=2
#error This is meant for a radix 2 system!
#endif

and go on with it.

Otherwise you need a factor of log(FLT_RADIX)/log(2) in there.

I have no idea how popular FLT_RADIX==10 machines will get over
the years, now that they are part of the IEEE standard.

-- glen
 

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

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top