Version française
Home     About     Download     Resources     Contact us    
Browse thread
[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: -- (:)
From: David Chase <chase@w...>
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.
     12345e-4 instead of 1.2345e+0 */
  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