[patch] problem with floats

Nirgal Vourgère <[email protected]> Sun, 6 Feb 2011 17:47:21 +0000
Newsgroups gmane.comp.db.mdb-tools.devel
Message-ID <[email protected]>
Hello

I have a problem introduced by the fix of http://bugs.debian.org/220403

Here was a part of the patch:
Index: mdbtools-0.6pre1/src/libmdb/data.c
===================================================================
--- mdbtools-0.6pre1.orig/src/libmdb/data.c
+++ mdbtools-0.6pre1/src/libmdb/data.c
@@ -857,7 +857,7 @@
        break;
        case MDB_FLOAT:
            tf = mdb_get_single(buf, start);
-           text = g_strdup_printf("%.*e",
+           text = g_strdup_printf("%.*f",
                FLT_DIG - floor_log10(tf,1) - 1, tf);
        break;
        case MDB_DOUBLE:


Rebuilding with MDB_DEBUG, I have this kind of output for prdata:
055b  00 24 64 46 
column 1 is 1.5e+04

Python tells me the output should be
struct.unpack('f', '\x00\x24\x64\x46')
14601.0

When reverting the patch, I get from prdata:
055b  00 24 64 46
column 1 is 14601.0

I tried 1e-7 that was supposed not to work, and was the reason the patch was introduced. I have no problem:
column 1 is 0.000000100000



You'll notice the unusual syntax "%.*f" that takes 2 arguments: the precision then the value.

I don't feel confortable exporting floats such as 1e-37 as a very long string, so I suggest we keep the 'e' format.

The precision however is wrong.
I was about to use FLT_DIG, but it is repported buggy. :/
Here, I have FLT_MANT_DIG==24 bits, meaning the maximum number without the exponent is 2^24=16777216
The number of digits in a decimal representation is ceil(log10(16777216))=8
The number of characters before the dot is not taken into account when specifying the precision
printf("%.*e\n", 3, 1.23456789) -> 1.235e+00
So that leave us with an extra number character. I assume this is usefull going arround roundings.

Does that sound ok?

Attached is the patch.
I added some '-lm' for the linker to find the builtin math functions. I'm not very familiar with automake, you'd better check I did it right.


Or maybe the original patch should just be reverted (for both MDB_FLOAT and MDB_DOUBLE)...

------------------------------------------------------------------------------
The modern datacenter depends on network connectivity to access resources
and provide services. The best practices for maximizing a physical server's
connectivity to a physical network are well understood - see how these
rules translate into the virtual world? 
http://p.sf.net/sfu/oracle-sfdevnlfb

_______________________________________________
mdbtools-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mdbtools-dev
floats.diff (text/x-patch, 2.5 KB)
Index: mdbtools-0.6pre1/src/libmdb/data.c
===================================================================
--- mdbtools-0.6pre1.orig/src/libmdb/data.c
+++ mdbtools-0.6pre1/src/libmdb/data.c
@@ -803,6 +803,7 @@
 	return text;
 }
 
+#if 0
 int floor_log10(double f, int is_single)
 {
 	unsigned int i;
@@ -831,6 +832,7 @@
 		return (int)i;
 	}
 }
+#endif
 
 char *mdb_col_to_string(MdbHandle *mdb, void *buf, int start, int datatype, int size)
 {
@@ -857,12 +859,12 @@
 		case MDB_FLOAT:
 			tf = mdb_get_single(buf, start);
 			text = g_strdup_printf("%.*e",
-				FLT_DIG - floor_log10(tf,1) - 1, tf);
+				(int)ceil(log10(1L<<FLT_MANT_DIG)), tf);
 		break;
 		case MDB_DOUBLE:
 			td = mdb_get_double(buf, start);
 			text = g_strdup_printf("%.*e",
-				DBL_DIG - floor_log10(td,0) - 1, td);
+				(int)ceil(log10(1L<<DBL_MANT_DIG)), td);
 		break;
 		case MDB_BINARY:
 		case MDB_TEXT:
Index: mdbtools-0.6pre1/src/libmdb/Makefile.am
===================================================================
--- mdbtools-0.6pre1.orig/src/libmdb/Makefile.am
+++ mdbtools-0.6pre1/src/libmdb/Makefile.am
@@ -2,4 +2,4 @@
 libmdb_la_SOURCES=	catalog.c mem.c file.c kkd.c table.c data.c dump.c backend.c money.c sargs.c index.c like.c write.c stats.c map.c props.c worktable.c options.c iconv.c
 libmdb_la_LDFLAGS = -version-info  1:0:0
 AM_CPPFLAGS	=	-I$(top_srcdir)/include $(GLIB_CFLAGS)
-LIBS = $(GLIB_LIBS) @LIBS@
+LIBS = $(GLIB_LIBS) @LIBS@ -lm
Index: mdbtools-0.6pre1/src/odbc/Makefile.am
===================================================================
--- mdbtools-0.6pre1.orig/src/odbc/Makefile.am
+++ mdbtools-0.6pre1/src/odbc/Makefile.am
@@ -16,7 +16,7 @@
 				$(patsubst %, $(MDBDIR)/%, \
 				$(patsubst %.c, %.lo, $(MDBSOURCES))) \
 				../libmdb/libmdb.la
-LIBS	=	@LEXLIB@ $(GLIB_LIBS) $(ODBC_LIBS)
+LIBS	=	@LEXLIB@ $(GLIB_LIBS) $(ODBC_LIBS) -lm
 unittest_LDADD	=	libmdbodbc.la ../libmdb/libmdb.la ../sql/libmdbsql.la
 
 ## Need blank statement to avoid compiling odbc.c
Index: mdbtools-0.6pre1/src/util/Makefile.am
===================================================================
--- mdbtools-0.6pre1.orig/src/util/Makefile.am
+++ mdbtools-0.6pre1/src/util/Makefile.am
@@ -1,6 +1,6 @@
 bin_PROGRAMS	=	mdb-export mdb-array mdb-schema mdb-tables mdb-parsecsv mdb-header mdb-sql mdb-ver mdb-prop 
 noinst_PROGRAMS = mdb-import prtable prcat prdata prkkd prdump prole updrow prindex
-LIBS	=	$(GLIB_LIBS) @LIBS@ @LEXLIB@ 
+LIBS	=	$(GLIB_LIBS) @LIBS@ @LEXLIB@ -lm
 DEFS = @DEFS@ -DLOCALEDIR=\"$(localedir)\"
 AM_CPPFLAGS	=	-I$(top_srcdir)/include $(GLIB_CFLAGS)
 LDADD	=	../libmdb/libmdb.la