Today I discovered while debugging a fairly complex application that I built under MinGW/MSYS/wine that the scanf family of functions was introducing float (32-bit floating-point) noise into double (64-bit floating-point) results.
I implemented a simple test code to make it extremely easy to replicate this issue:
cat test_fscanf.c #include <stdlib.h> #include <stdio.h> void main(void) { double x; while(fscanf(stdin, " %le ", &x) == 1) { printf("%25.17e\n", x); } }
On Linux you can build it and run it with these expected results with some numerical noise in the last place:
gcc test_fscanf.c echo "1.1e+01 1.1e+00 1.1e-01 1.1e-02 1.1e-03 1.1e-04" | ./a.out 1.10000000000000000e+01 1.10000000000000009e+00 1.10000000000000001e-01 1.09999999999999994e-02 1.10000000000000007e-03 1.10000000000000004e-04
But if you do the same build on wine you get these noisy results for all the values with negative exponents (but positive exponents are fine for some reason).
echo "1.1e+01 1.1e+00 1.1e-01 1.1e-02 1.1e-03 1.1e-04" | ./a.exe 1.10000000000000000e+001 1.10000000000000009e+000 1.10000001639127737e-001 1.10000003278255491e-002 1.10000004917383261e-003 1.10000006556511075e-004
The level of noise is consistent with some float (as opposed to double) logic incorrectly being used in the fscanf library function for negative exponents, and I had similar bad numerical noise results from sscanf with my complex application.
My hardware is 64-bit. My wine is 32-bit wine-1.3.27 built on a Debian Squeeze box with the standard 32-bit Debian build dependencies for wine. The wine gcc is from the MinGW version you get with the automatic MinGW/MSYS installer from a few days ago. It's version number is
bash.exe-3.1$ gcc --version gcc.exe (GCC) 4.5.2 ...
The above wine test was run in a wineconsole running the MSYS version of bash.
So for my wine installation (which has no access to Microsoft libraries), how can I find out which library is providing the fscanf functionality that is introducing float noise into double results for the above test programme? I need that information so that I can properly report the above bug.
If someone here knows exactly where to make the fix and is inspired to do so, I would be happy to test the result with my more complex ephcom2 application (reading and interpolating JPL ephemerides, see http://sourceforge.net/news/?group_id=567377&id=302987 for the latest release announcement). That release was POSIX only, but I hope to make the next version work properly on Windows as well. The current status is that ephcom2 builds and mostly tests well under wine except for the above numerical noise in sscanf results which I would like to get rid of to see if there are any other remaining generic Windows issues in the software.
Alan __________________________ Alan W. Irwin
Astronomical research affiliation with Department of Physics and Astronomy, University of Victoria (astrowww.phys.uvic.ca).
Programming affiliations with the FreeEOS equation-of-state implementation for stellar interiors (freeeos.sf.net); the Time Ephemerides project (timeephem.sf.net); PLplot scientific plotting software package (plplot.sf.net); the libLASi project (unifont.org/lasi); the Loads of Linux Links project (loll.sf.net); and the Linux Brochure Project (lbproject.sf.net). __________________________
Linux-powered Science __________________________
On Mon, Aug 29, 2011 at 06:43:41PM -0700, Alan W. Irwin wrote:
double x; while(fscanf(stdin, " %le ", &x) == 1)
You are using the wrong format, %le is for 'long double', this will probably overwrite too much data.
David
Den 2011-08-30 20:18 skrev David Laight:
On Mon, Aug 29, 2011 at 06:43:41PM -0700, Alan W. Irwin wrote:
double x; while(fscanf(stdin, " %le ", &x) == 1)
You are using the wrong format, %le is for 'long double', this will probably overwrite too much data.
Nope, you are mistaken and the OP is correct.
%e float %le double %Le long double
Cheers, Peter
Le 30/08/2011 20:38, Peter Rosin a écrit :
Den 2011-08-30 20:18 skrev David Laight:
On Mon, Aug 29, 2011 at 06:43:41PM -0700, Alan W. Irwin wrote:
double x; while(fscanf(stdin, " %le ",&x) == 1)
You are using the wrong format, %le is for 'long double', this will probably overwrite too much data.
Nope, you are mistaken and the OP is correct.
%e float %le double %Le long double
Cheers, Peter
from what I understand, double and long double have the same precision under msvc, while they don't on linux (and gcc) likely a problematic conversion somewhere in the code path A+