This site is updated infrequently. For up-to-date information, please visit the new OCaml website at ocaml.org.

[Caml-list] float pretty-printing precision, once more.
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
 Date: 2002-12-11 (04:04) From: David Chase Subject: Re: [Caml-list] float pretty-printing precision, once more.
```At 04:47 PM 12/10/2002 +0100, Xavier Leroy wrote:
>If that was really the best approximation, there would be nothing to
>argue.  But both 0.10000000000000001 and 0.1 read back as identical
>floats, so the latter should be printed instead, but sprintf (on
>Linux at least) is too stupid to realize this.

Gdtoa will supply you with the non-stupid answer, if you care
to ask it.  Again -- this I know well, I have used gdtoa to get
specification-conforming double->String conversion in a Java
VM/library.  Here is a test program that demonstrates how to
use gdtoa in "minimum unambiguous result length" mode.  This
assumes int is 32 bits long:

#include "gdtoa.h"
/* Always define to zero or one.  It is zero on Pentium. */
#define LITTLE_ENDIAN 1
FPI d_convert = { 53, 1-1023-53+1, 2046-1023-53+1, FPI_Round_near, 0};
union pun {
double d;
int i[2];
};
char * test_gdtoa(double d, int mode, int ndigits, int * plength, int * pdecpt) {
union pun convert;
convert.d = d;
{
int i0 = convert.i[0^LITTLE_ENDIAN];
int i1 = convert.i[1^LITTLE_ENDIAN];

int isNeg = i0 < 0;
int m0 = i0 & 0xfffff;
int e0 = ((unsigned)i0 >> 20) & 0x7ff;
int int_args[8];
char * ptr_args[1];
char * result;
int length;

/* NaN or Inf */
if (e0 == 0x7ff) {
if ((m0 | i1) != 0) {
*plength = -1;
return "NaN";
} else {
*plength = -1;
return isNeg ? "-Infinity" : "Infinity";
}
}

/* +/- 0 */
if ((m0 | i1 | e0) == 0) {
*plength = -1;
return isNeg ? "-0.0" : "0.0";
}

/* If the exponent is larger than zero,
then the leading "1" in the mantisssa
is implicit.  Otherwise, the number is
denormalized, and the exponent is
really 1. */

if (e0 != 0) m0 |= 0x100000;
else e0 = 1;

/* Adjust exponent to remove bias and to
make the mantissa all "integer", e.g.
e0 -= 0x3ff + 52;
int_args[0] = i1;
int_args[1] = m0;
int_args[2] = STRTOG_Normal;
result = gdtoa(&d_convert, /* fpi */
e0,         /* be   */
int_args + 0, /* bits */
int_args + 2, /* kindP */
mode,         /* mode */
ndigits,      /* ndigits */
int_args + 3, /* decpt */
ptr_args + 0); /* rve */
*pdecpt = int_args[3];
length = ptr_args[0] - result;
if (length == 0) {
*plength = -1;
return isNeg ? "-0.0" : "0.0";
}
*plength = length;
return result;
}
}

static test_one(double d) {
int decpt;
int length;
char * result = test_gdtoa(d, 0, 0, &length, &decpt);

if (length == -1) {
printf("test of %f returns special value %s\n", d, result);
} else {
printf("test of %f returns regular value %s, decpt %d, length %d\n", d, result, decpt, length);
}
}

int main(int argc, char ** argv) {
test_one(1.0);
test_one(1.0/0.0);
test_one(-1.0/0.0);
test_one(-1.0/0.0 + 1.0/0.0);
test_one(0.0);
test_one(-0.0);
test_one(-1.0);
test_one(0.25);
test_one(4.0);
test_one(8192.125);
test_one(0.1);
test_one(0.01);
test_one(0.9);
test_one(0.09);
test_one(0.2);
test_one(0.02);
test_one(0.3);
test_one(0.03);
}

David Chase

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners

```