Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

function eng.c in snippets

39 views
Skip to first unread message

Dan Stubbs

unread,
Jul 12, 1997, 3:00:00 AM7/12/97
to

The snippets package of C/C++ functions is referenced from time to time
in several news groups. It is a very commendable collection of
implementations of important algorithms.

I had occassion to refer to function eng.c in that collection. This
function converts a double to an engineering notation as shown below.

74088 = 74.088 k
1.30691e+08 = 130.69 M
5.48903e+09 = 5.4890 G
9.68265e+12 = 9.6827 T

I found several problems with eng.c: (a) a logic error, (b) right
justification was different for positive and negative values,
(c) behavior for very large or very small valuse was undefined,
(d) reference to snipmath.h even though the declaration of eng.c was
not contained in that file.

I corrected some of these problems. I am including my code below
because I am very impressed with the ability of the readers of this
newsgroup to take such an algorithm and really get it right. I suggest
that the result replace eng.c in the snippets collection.

Most of what this function does is prepare to call sprintf--where most
of the work is done. I wonder if there isnUt a much simpler way to
do this.

I am also including (a somewhat compacted--but otherwise unchanged) copy
of the code currently in snippets. A summary of the changes I made is
placed between the two versions of the function.

char *eng (double value, int places) {
const char *const prefixes[] = {
"a","f","p","n","f","m","","k","M","G","T"};
int p = 6;
static char result[30];
char *res = result;

*res++ = (value >= 0) ? ' ' : '-';
value = (value >= 0) ? value : -value;

while (p-- > 0 && value != 0 && value < 1.0)
value *= 1000.;
while (p++ < 10 && value != 0 && value > 1000.)
value /= 1000;
places = (value >= 100.) ? places-2 :
(value >= 10.) ? places-1 : places;
sprintf(res, "%.*f %s", places-1, value, prefixes[p]);
return result;
}
+----------------------------------------------------------------------+

(0) Change to a more compact style.
(1) Change > to >= in updating identifier places. This corrects a
logic error in this function. Also change the way the
computation is made.
(2) Reformat test output to a more attractive form.
(3) Modify the two while loops to make them shorter and thus
(IMO) easier to read.
(4) Change initialization of res so that both positive and
negative values right justify the same.
(5) Note that although #include snipmath.h appears, this
function's declaration is not in shipmath.h.
(6) If the value is too large (or small) to be converted the
result is undefined--depending on how the compiler handles
this code. What is the best way to fix this?

Here is the content of eng.c

/* +++Date last modified: 05-Jul-1997 */
/* ENG.C - Format floating point in engineering notation */
/* Released to public domain by author, David Harmon, Jan. 1994 */

#include <stdio.h>
#include "snipmath.h"

char *eng(double value, int places) {
const char *const prefixes[] = {
"a","f","p","n","f","m","","k","M","G","T"};
int p = 6;
static char result[30];
char *res = result;

if (value < 0.) {
*res++ = '-';
value = -value;
}
while (value != 0 && value < 1. && p > 0) {
value *= 1000.;
p--;
}
while (value != 0 && value > 1000. && p < 10 ) {
value /= 1000.;
p++;
}
if (value > 100.)
places--;
if (value > 10.)
places--;
sprintf(res, "%.*f %s", places-1, value, prefixes[p]);
return result;
}

#include <stdio.h>

main()
{
double w;
for (w = 1e-19; w < 1e16; w *= 42)
printf(" %g W = %sW\n", w, eng(w, 3));
return 0;
}


Stephan Wilms

unread,
Jul 14, 1997, 3:00:00 AM7/14/97
to

Dan Stubbs wrote:
>
> The snippets package of C/C++ functions is referenced from time to time
> in several news groups. It is a very commendable collection of
> implementations of important algorithms.
>
> I had occassion to refer to function eng.c in that collection. This
> function converts a double to an engineering notation as shown below.
>
> 74088 = 74.088 k
> 1.30691e+08 = 130.69 M
> 5.48903e+09 = 5.4890 G
> 9.68265e+12 = 9.6827 T
>
> I found several problems with eng.c: (a) a logic error, (b) right
> justification was different for positive and negative values,
> (c) behavior for very large or very small valuse was undefined,
> (d) reference to snipmath.h even though the declaration of eng.c was
> not contained in that file.

Please post a copy of this message to Bob Stout who maintains the
SNIPPETS collection. I'm sure, he will be interest in this. His e-mail
adress is: r...@snippets.org

Stephan
(initiator of the campaign against grumpiness in c.l.c)

Sven

unread,
Jul 14, 1997, 3:00:00 AM7/14/97
to Dan Stubbs

Dan Stubbs wrote:
>
> The snippets package of C/C++ functions is referenced from time to time
> in several news groups. It is a very commendable collection of
> implementations of important algorithms.
>
> I had occassion to refer to function eng.c in that collection. This
> function converts a double to an engineering notation as shown below.
>
> 74088 = 74.088 k
> 1.30691e+08 = 130.69 M
> 5.48903e+09 = 5.4890 G
> 9.68265e+12 = 9.6827 T
>
> I found several problems with eng.c: (a) a logic error, (b) right
[snip]

I question "commendable collection of implementations of important
algorithms" based on this example. It seems that an understanding of
logarithms could eliminate all loops in this code.

User923005

unread,
Jul 18, 1997, 3:00:00 AM7/18/97
to

>>
I question "commendable collection of implementations of important
algorithms" based on this example. It seems that an understanding of
logarithms could eliminate all loops in this code.
<<
Really? Did you time the two methods? A call to log(x) is fairly
expensive.

I'm at home, so I say anything I please.


0 new messages