Sensibly printed floats?

A

Adam Warner

Hi all,

I'm used to ANSI Common Lisp implementations sanely printing single and
double floats. By sane I mean the printed decimal representation mimics
the underlying binary precision of the float. For example:

[1]> (coerce 2/3 'single-float)
0.6666667
[2]> (coerce 2/300 'single-float)
0.006666667
[3]> (coerce 2/3 'double-float)
0.6666666666666666d0
[4]> (coerce 2/300 'double-float)
0.006666666666666667d0
[5]> (coerce 2/30000 'double-float)
6.666666666666667d-5

Does C99 provide a method to print floats this way (apart from `f', `d'
etc. exponential markers)?

Regards,
Adam
 
E

Eric Sosman

Adam said:
Hi all,

I'm used to ANSI Common Lisp implementations sanely printing single and
double floats. By sane I mean the printed decimal representation mimics
the underlying binary precision of the float. For example:

[1]> (coerce 2/3 'single-float)
0.6666667
[2]> (coerce 2/300 'single-float)
0.006666667
[3]> (coerce 2/3 'double-float)
0.6666666666666666d0
[4]> (coerce 2/300 'double-float)
0.006666666666666667d0
[5]> (coerce 2/30000 'double-float)
6.666666666666667d-5

Does C99 provide a method to print floats this way (apart from `f', `d'
etc. exponential markers)?

I'm not entirely sure I understand what you mean by
"this way," but perhaps the "%g" conversion specifier is
what you're looking for.
 
M

Malcolm

Adam Warner said:
I'm used to ANSI Common Lisp implementations sanely printing single and
double floats. By sane I mean the printed decimal representation mimics
the underlying binary precision of the float. For example:

[1]> (coerce 2/3 'single-float)
0.6666667
[2]> (coerce 2/300 'single-float)
0.006666667
[3]> (coerce 2/3 'double-float)
0.6666666666666666d0
[4]> (coerce 2/300 'double-float)
0.006666666666666667d0
[5]> (coerce 2/30000 'double-float)
6.666666666666667d-5

Does C99 provide a method to print floats this way (apart from `f', `d'
etc. exponential markers)?
The %g and %f flags take "width" and "precision" markers.

To print a float for human consumption, just use a bare %g. To print out for
machine accuracy, use %*g and pass DBL_DIG as the specifier. This will allow
you to convert between text and binary and back with no loss of precision.

To print in tables, mess about with the width specifier and %f. As a last
resort you can write your own formatting routine, but you shouldn't have to
do this for general-purpose programming.
 
M

Martin Ambuhl

Adam said:
Hi all,

I'm used to ANSI Common Lisp implementations sanely printing single and
double floats. By sane I mean the printed decimal representation mimics
the underlying binary precision of the float. For example:

[1]> (coerce 2/3 'single-float)
0.6666667
[2]> (coerce 2/300 'single-float)
0.006666667
[3]> (coerce 2/3 'double-float)
0.6666666666666666d0
[4]> (coerce 2/300 'double-float)
0.006666666666666667d0
[5]> (coerce 2/30000 'double-float)
6.666666666666667d-5

Does C99 provide a method to print floats this way (apart from `f', `d'
etc. exponential markers)?

Not just C99, but earlier versions of C as well:

#include <stdio.h>
#include <float.h>

int main(void)
{
printf("2/3 single-float: %.*g\n", FLT_DIG, 2.f / 3.f);
printf("2/300 single-float: %.*g\n", FLT_DIG, 2.f / 300.f);
printf("2/3 double-float: %.*g\n", DBL_DIG, 2. / 3.);
printf("2/300 double-float: %.*g\n", DBL_DIG, 2. / 300.);
printf("2/30000 double-float: %.*g\n", DBL_DIG, 2. / 30000.);
return 0;
}

2/3 single-float: 0.666667
2/300 single-float: 0.00666667
2/3 double-float: 0.666666666666667
2/300 double-float: 0.00666666666666667
2/30000 double-float: 6.66666666666667e-05
 
A

Adam Warner

Hi Martin Ambuhl,
Not just C99, but earlier versions of C as well:

#include <stdio.h>
#include <float.h>

int main(void)
{
printf("2/3 single-float: %.*g\n", FLT_DIG, 2.f / 3.f);
printf("2/300 single-float: %.*g\n", FLT_DIG, 2.f / 300.f);
printf("2/3 double-float: %.*g\n", DBL_DIG, 2. / 3.);
printf("2/300 double-float: %.*g\n", DBL_DIG, 2. / 300.);
printf("2/30000 double-float: %.*g\n", DBL_DIG, 2. / 30000.);
return 0;
}

2/3 single-float: 0.666667
2/300 single-float: 0.00666667
2/3 double-float: 0.666666666666667
2/300 double-float: 0.00666666666666667
2/30000 double-float: 6.66666666666667e-05

Thanks everyone! Coupled with the # modifier (so e.g. 666667.f prints as
666667. instead of 666667) it should always be possible to dynamically
distinguish a printed float from an integer.

Regards,
Adam
 

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,159
Messages
2,570,883
Members
47,414
Latest member
djangoframe

Latest Threads

Top