Re: [sqlite] VERY weird rounding error

2012-06-17 Thread Doug Currie

On Jun 17, 2012, at 12:23 PM, Keith Medcalf wrote:

> SQLITE_SIGNIFICANT_DIGITS defaults to 14, but you can override it.  No matter 
> what is requested, the maximum number of significant digits is limited to the 
> specification, and rounding is applied to the remaining bits of the 
> significand, to round to the specified number of significant digits. 

FYI, the venerable approach:

http://kurtstephens.com/files/p372-steele.pdf

ftp://ftp.ccs.neu.edu/pub/people/will/retrospective.pdf

http://www.cs.washington.edu/education/courses/cse590p/590k_02au/print-fp.pdf

http://www.cesura17.net/~will/Professional/Research/Papers/howtoread.pdf

e

___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] VERY weird rounding error

2012-06-17 Thread Etienne
Hi all,

Here is a summary of my investigations related to the "0.1 case".

[FYI, 8674146.01 is another example]

The short (and censured :-) version: WTF!? That's just insane!!!

Look at this (sqlite3.c compiled only ONE TIME with default options):

[---
test.js:
  var db = new SQLite();
  db.exec("select 0.1", function(r){writeln(r)});
---

JSDB under GDB:

(gdb) break sqlite3.c:19917
Breakpoint 1 at 0x57d82d: file sqlite3.c, line 19917.
(gdb) run
Starting program: R:\jsdb/jsdb.exe test.js
[New Thread 21228.0x52f8]

Breakpoint 1, sqlite3VXPrintf (pAccum=0x22e184, useExtended=0,
fmt=0x65323d "g", ap=0x22e1f4 "") at sqlite3.c:19917
19917   realvalue /= 10.0;
(gdb) print ((unsigned char *) &realvalue)[0]@13
$1 = "\000ÐÌÌÌ\fKÃ\017@\000\000Ú"
(gdb) n
19918   exp++;
(gdb) print ((unsigned char *) &realvalue)[0]@13
$2 = "\000Ø£p=\n=1e32 && exp<=350 ){ realvalue /= 1e32; exp+=32; }
  while( realvalue>=1e8 && exp<=350 ){ realvalue /= 1e8; exp+=8; }
  while( realvalue>=10.0 && exp<=350 ){ realvalue /= 10.0; exp++; }

2) decreasing the max number of required mult.

19910,19911c
  if( realvalue>=1e16 && exp<=350 ){ realvalue *= 1e-16; exp+=16; }
  if( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
  if( realvalue>=1e4 && exp<=350 ){ realvalue *= 1e-4; exp+=4; }
  if( realvalue>=1e2 && exp<=350 ){ realvalue *= 1e-2; exp+=2; }
  if( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }


I trust you guys, for fixing SQLite smoothly.

A big thank you for your patch Keith.

Keep up the very good work


Etienne
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-17 Thread Keith Medcalf

As long as the digit to the left of the decimal point is zero, and the digit 
immediately following the decimal point is non-zero, then yes.  (ie, the same 
rules as apply for normalizing the coefficient in binary, where the most 
significant binary digit must be a one).  

Actually, you can achieve 15 and even 16 significant digits in double precision 
floating point if you are very very careful with your numerical methods.  It is 
astonishingly easy to reduce that to a mere 10 or less digits however.  It 
really depends on your audience.

You can see this pretty easily.  Apply the following patch to the amalgamation. 
 It allows you to "set" the significant digits via a compiler directive 
SQLITE_SIGNIFICANT_DIGITS.  All the formatted output calls are requesting 
"%[!].16g" as their output format (that is, I have made them all consistent 
with the longest precision specified in the code).  SQLITE_SIGNIFICANT_DIGITS 
defaults to 14, but you can override it.  No matter what is requested, the 
maximum number of significant digits is limited to the specification, and 
rounding is applied to the remaining bits of the significand, to round to the 
specified number of significant digits.  Then try with various settings for the 
pre-processor directive.  You will note that you get somewhat irrational 
results when significant digits is set at 16.  Erroneous results at 15, and 
accurate 14 digit results at 14.  Setting the number of significant digits to 
less than 14 simply limits the output precision (but remains accurate to the
  specified number of significant digits).  Again, it depends on your audience 
and what they expect.

--- sqlite3.c
+++ sqlite3.c
@@ -19594,17 +19594,20 @@
 ** Example:
 ** input: *val = 3.14159
 ** output:*val = 1.4159function return = '3'
 **
 ** The counter *cnt is incremented each time.  After counter exceeds
-** 16 (the number of significant digits in a 64-bit float) '0' is
-** always returned.
+** SQLITE_SIGNIFICANT_DIGITS '0' is always returned.  Default to 14
+** digits for IEEE 754 Floating Point
 */
+#ifndef SQLITE_SIGNIFICANT_DIGITS
+#define SQLITE_SIGNIFICANT_DIGITS 14
+#endif
 static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
   int digit;
   LONGDOUBLE_TYPE d;
-  if( (*cnt)++ >= 16 ) return '0';
+  if( (*cnt)++ >= SQLITE_SIGNIFICANT_DIGITS ) return '0';
   digit = (int)*val;
   d = digit;
   digit += '0';
   *val = (*val - d)*10.0;
   return (char)digit;
@@ -19878,11 +19881,11 @@
   case etGENERIC:
 realvalue = va_arg(ap,double);
 #ifdef SQLITE_OMIT_FLOATING_POINT
 length = 0;
 #else
-if( precision<0 ) precision = 6; /* Set default precision */
+if( precision<0 || precision>SQLITE_SIGNIFICANT_DIGITS ) precision = 
SQLITE_SIGNIFICANT_DIGITS; /* Set default prec
ision */
 if( realvalue<0.0 ){
   realvalue = -realvalue;
   prefix = '-';
 }else{
   if( flag_plussign )  prefix = '+';
@@ -59458,11 +59461,11 @@
   */
   if( fg & MEM_Int ){
 sqlite3_snprintf(nByte, pMem->z, "%lld", pMem->u.i);
   }else{
 assert( fg & MEM_Real );
-sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r);
+sqlite3_snprintf(nByte, pMem->z, "%!.16g", pMem->r);
   }
   pMem->n = sqlite3Strlen30(pMem->z);
   pMem->enc = SQLITE_UTF8;
   pMem->flags |= MEM_Str|MEM_Term;
   sqlite3VdbeChangeEncoding(pMem, enc);
@@ -65065,11 +65068,11 @@
   if( pVar->flags & MEM_Null ){
 sqlite3StrAccumAppend(&out, "NULL", 4);
   }else if( pVar->flags & MEM_Int ){
 sqlite3XPrintf(&out, "%lld", pVar->u.i);
   }else if( pVar->flags & MEM_Real ){
-sqlite3XPrintf(&out, "%!.15g", pVar->r);
+sqlite3XPrintf(&out, "%!.16g", pVar->r);
   }else if( pVar->flags & MEM_Str ){
 #ifndef SQLITE_OMIT_UTF16
 u8 enc = ENC(db);
 if( enc!=SQLITE_UTF8 ){
   Mem utf8;


---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org


> -Original Message-
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of Black, Michael (IS)
> Sent: Sunday, 17 June, 2012 07:17
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] VERY weird rounding error
> 
> I think I figured out your "14" reference.
> 
> What you mean is the number of fractional digits on the coefficient which
> equates to 15 significant digits including the single digit left of the
> decimal point.  So your "expected precision" is really "scientific notation
> fractional precision".
> 
> 
> 
> My world makes sense again.
> 
> 
> 
> 
> 

Re: [sqlite] VERY weird rounding error

2012-06-17 Thread Keith Medcalf

No references -- but everything is an estimate.  Unlike decimal/BCD (IEEE 
854-2008, GDAS, etc) you cannot map binary precision directly to decimal 
precision.  This is especially true since your last bits of precision will 
suffer as you perform the conversion to decimal.  I was always told (and 
understood) that fast'n'cheap floating point (16-bit) was just as accurate as a 
slide rule.

All formats have some "extra bits" of precision which, like the slide rule, are 
useful for estimating the rounding of the least significant digit.  For this to 
be true you have to have some extra bits in reserve.  Generally speaking though 
even counting on 14 accurate decimal digits from double precision floating 
point is pushing the limits of precision.  I'd use Quad precision for 
computation if I really needed accuracy to 14-16 significant digits.  That 
doesn't mean that you can't get 15 or 16 significant digits from double 
precision, merely that you have to really understand the numerical methods 
being used to actually be certain that precision has been maintained.

Then again, some people were still building things using two digit years in 
1990.

---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org

> -Original Message-
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of Black, Michael (IS)
> Sent: Sunday, 17 June, 2012 06:38
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] VERY weird rounding error
> 
> Do you have a reference for this?  I found 3:
> 
> 
> 
> Wikipedia says 16
> 
> http://en.wikipedia.org/wiki/IEEE_754-2008
> 
> BYU says 15
> 
> http://www.math.byu.edu/~schow/work/IEEEFloatingPoint.htm
> 
> Oracle says 15-17
> 
> http://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html
> 
> 
> 
> But I've never heard of "expected precision" and google doesn't come up with
> term either -- it either has precision or it doesn't as far as I've ever
> heard.  And i've never heard of 14 digits before (which wouidn't surprise me
> though).
> 
> 
> 
> 
> 
> Michael D. Black
> 
> Senior Scientist
> 
> Advanced Analytics Directorate
> 
> Advanced GEOINT Solutions Operating Unit
> 
> Northrop Grumman Information Systems
> 
> 
> From: sqlite-users-boun...@sqlite.org [sqlite-users-boun...@sqlite.org] on
> behalf of Keith Medcalf [kmedc...@dessus.com]
> Sent: Saturday, June 16, 2012 8:11 PM
> To: General Discussion of SQLite Database
> Subject: EXT :Re: [sqlite] VERY weird rounding error
> 
> 
> > Ideally, you write your software so that differences in the 15th decimal
> > place don't matter to you.  If you want two platforms to give identical
> > results you use integer arithmetic.  It really depends on what kind of
> > application you're writing (scientific, financial) or what your numbers
> > actually represent.
> 
> This is technically incorrect.  Floating Point accuracy is in Decimal Digits,
> not Decimal Places (unless, of course, the decimal formatted output is in
> "Engineering Notation" in which case Decimal Digits == Decimal Places --
> Engineering Notation means that the number to the left of the decimal point
> is 0).
> 
> The "theoretical" accuracy (and the "reasonably expected" accuracy) is:
> 
> Half (2 Bytes)   ~ 3.32
> Single (4 Bytes) ~ 7.26
> Double (8 bytes)~15.9   14
> Double extended (10 Byte)   ~19.2   18
> Quad (  16 Bytes)   ~34.0   32
> 
> The value 9990.1 has 5 significant digits.
> The output value 0.11 has 15 significant digits, of which the
> expected 14 are accurate.
> 
> Etienne, thanks for the thanks.
> 
> ---
> ()  ascii ribbon campaign against html e-mail
> /\  www.asciiribbon.org<http://www.asciiribbon.org/>
> 
> 
> > -Original Message-
> > From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> > boun...@sqlite.org] On Behalf Of Simon Slavin
> > Sent: Saturday, 16 June, 2012 17:33
> > To: General Discussion of SQLite Database
> > Subject: Re: [sqlite] VERY weird rounding error
> >
> >
> > On 17 Jun 2012, at 12:06am, Etienne  wrote:
> >
> > > Is there a trick (in the sys. libraries mentioned above, or through the
> > win32 C API) for changing the way the FPU handles (long) doubles?
> >
> > You're at tricky low level detail now.  Rounding and truncation modes used
> by
> > chips which implement IEEE754 are often carefully set by compiler writers
> to
&

Re: [sqlite] VERY weird rounding error

2012-06-17 Thread Black, Michael (IS)
I think I figured out your "14" reference.

What you mean is the number of fractional digits on the coefficient which 
equates to 15 significant digits including the single digit left of the decimal 
point.  So your "expected precision" is really "scientific notation fractional 
precision".



My world makes sense again.





Michael D. Black

Senior Scientist

Advanced Analytics Directorate

Advanced GEOINT Solutions Operating Unit

Northrop Grumman Information Systems


From: sqlite-users-boun...@sqlite.org [sqlite-users-boun...@sqlite.org] on 
behalf of Black, Michael (IS) [michael.bla...@ngc.com]
Sent: Sunday, June 17, 2012 7:38 AM
To: General Discussion of SQLite Database
Subject: EXT :Re: [sqlite] VERY weird rounding error

Do you have a reference for this?  I found 3:



Wikipedia says 16

http://en.wikipedia.org/wiki/IEEE_754-2008

BYU says 15

http://www.math.byu.edu/~schow/work/IEEEFloatingPoint.htm

Oracle says 15-17

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html



But I've never heard of "expected precision" and google doesn't come up with 
term either -- it either has precision or it doesn't as far as I've ever heard. 
 And i've never heard of 14 digits before (which wouidn't surprise me though).





Michael D. Black

Senior Scientist

Advanced Analytics Directorate

Advanced GEOINT Solutions Operating Unit

Northrop Grumman Information Systems


From: sqlite-users-boun...@sqlite.org [sqlite-users-boun...@sqlite.org] on 
behalf of Keith Medcalf [kmedc...@dessus.com]
Sent: Saturday, June 16, 2012 8:11 PM
To: General Discussion of SQLite Database
Subject: EXT :Re: [sqlite] VERY weird rounding error


> Ideally, you write your software so that differences in the 15th decimal
> place don't matter to you.  If you want two platforms to give identical
> results you use integer arithmetic.  It really depends on what kind of
> application you're writing (scientific, financial) or what your numbers
> actually represent.

This is technically incorrect.  Floating Point accuracy is in Decimal Digits, 
not Decimal Places (unless, of course, the decimal formatted output is in 
"Engineering Notation" in which case Decimal Digits == Decimal Places -- 
Engineering Notation means that the number to the left of the decimal point is 
0).

The "theoretical" accuracy (and the "reasonably expected" accuracy) is:

Half (2 Bytes)   ~ 3.32
Single (4 Bytes) ~ 7.26
Double (8 bytes)~15.9   14
Double extended (10 Byte)   ~19.2   18
Quad (  16 Bytes)   ~34.0   32

The value 9990.1 has 5 significant digits.
The output value 0.11 has 15 significant digits, of which the 
expected 14 are accurate.

Etienne, thanks for the thanks.

---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org<http://www.asciiribbon.org/>


> -Original Message-
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of Simon Slavin
> Sent: Saturday, 16 June, 2012 17:33
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] VERY weird rounding error
>
>
> On 17 Jun 2012, at 12:06am, Etienne  wrote:
>
> > Is there a trick (in the sys. libraries mentioned above, or through the
> win32 C API) for changing the way the FPU handles (long) doubles?
>
> You're at tricky low level detail now.  Rounding and truncation modes used by
> chips which implement IEEE754 are often carefully set by compiler writers to
> get the results they want.  If you mess with the settings they've chosen, you
> can get unexpected results in other apps which were previously working
> correctly.
>
>
> It's discovering and caring about this sort of thing that separates out the
> professional programmer from the someone who shouldn't be paid for
> programming.
>
> I do appreciate your thanks, by the way.
>
> Simon.
> ___
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users



___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-17 Thread Black, Michael (IS)
Do you have a reference for this?  I found 3:



Wikipedia says 16

http://en.wikipedia.org/wiki/IEEE_754-2008

BYU says 15

http://www.math.byu.edu/~schow/work/IEEEFloatingPoint.htm

Oracle says 15-17

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html



But I've never heard of "expected precision" and google doesn't come up with 
term either -- it either has precision or it doesn't as far as I've ever heard. 
 And i've never heard of 14 digits before (which wouidn't surprise me though).





Michael D. Black

Senior Scientist

Advanced Analytics Directorate

Advanced GEOINT Solutions Operating Unit

Northrop Grumman Information Systems


From: sqlite-users-boun...@sqlite.org [sqlite-users-boun...@sqlite.org] on 
behalf of Keith Medcalf [kmedc...@dessus.com]
Sent: Saturday, June 16, 2012 8:11 PM
To: General Discussion of SQLite Database
Subject: EXT :Re: [sqlite] VERY weird rounding error


> Ideally, you write your software so that differences in the 15th decimal
> place don't matter to you.  If you want two platforms to give identical
> results you use integer arithmetic.  It really depends on what kind of
> application you're writing (scientific, financial) or what your numbers
> actually represent.

This is technically incorrect.  Floating Point accuracy is in Decimal Digits, 
not Decimal Places (unless, of course, the decimal formatted output is in 
"Engineering Notation" in which case Decimal Digits == Decimal Places -- 
Engineering Notation means that the number to the left of the decimal point is 
0).

The "theoretical" accuracy (and the "reasonably expected" accuracy) is:

Half (2 Bytes)   ~ 3.32
Single (4 Bytes) ~ 7.26
Double (8 bytes)~15.9   14
Double extended (10 Byte)   ~19.2   18
Quad (  16 Bytes)   ~34.0   32

The value 9990.1 has 5 significant digits.
The output value 0.11 has 15 significant digits, of which the 
expected 14 are accurate.

Etienne, thanks for the thanks.

---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org<http://www.asciiribbon.org/>


> -Original Message-
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of Simon Slavin
> Sent: Saturday, 16 June, 2012 17:33
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] VERY weird rounding error
>
>
> On 17 Jun 2012, at 12:06am, Etienne  wrote:
>
> > Is there a trick (in the sys. libraries mentioned above, or through the
> win32 C API) for changing the way the FPU handles (long) doubles?
>
> You're at tricky low level detail now.  Rounding and truncation modes used by
> chips which implement IEEE754 are often carefully set by compiler writers to
> get the results they want.  If you mess with the settings they've chosen, you
> can get unexpected results in other apps which were previously working
> correctly.
>
>
> It's discovering and caring about this sort of thing that separates out the
> professional programmer from the someone who shouldn't be paid for
> programming.
>
> I do appreciate your thanks, by the way.
>
> Simon.
> ___
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users



___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-16 Thread Keith Medcalf

> Ideally, you write your software so that differences in the 15th decimal
> place don't matter to you.  If you want two platforms to give identical
> results you use integer arithmetic.  It really depends on what kind of
> application you're writing (scientific, financial) or what your numbers
> actually represent.

This is technically incorrect.  Floating Point accuracy is in Decimal Digits, 
not Decimal Places (unless, of course, the decimal formatted output is in 
"Engineering Notation" in which case Decimal Digits == Decimal Places -- 
Engineering Notation means that the number to the left of the decimal point is 
0).  

The "theoretical" accuracy (and the "reasonably expected" accuracy) is:

Half (2 Bytes)  ~ 3.32
Single (4 Bytes)~ 7.26
Double (8 bytes)~15.9   14
Double extended (10 Byte)   ~19.2   18
Quad (  16 Bytes)   ~34.0   32

The value 9990.1 has 5 significant digits.  
The output value 0.11 has 15 significant digits, of which the 
expected 14 are accurate.

Etienne, thanks for the thanks.

---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org


> -Original Message-
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of Simon Slavin
> Sent: Saturday, 16 June, 2012 17:33
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] VERY weird rounding error
> 
> 
> On 17 Jun 2012, at 12:06am, Etienne  wrote:
> 
> > Is there a trick (in the sys. libraries mentioned above, or through the
> win32 C API) for changing the way the FPU handles (long) doubles?
> 
> You're at tricky low level detail now.  Rounding and truncation modes used by
> chips which implement IEEE754 are often carefully set by compiler writers to
> get the results they want.  If you mess with the settings they've chosen, you
> can get unexpected results in other apps which were previously working
> correctly.
> 
> 
> It's discovering and caring about this sort of thing that separates out the
> professional programmer from the someone who shouldn't be paid for
> programming.
> 
> I do appreciate your thanks, by the way.
> 
> Simon.
> ___
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users



___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-16 Thread Simon Slavin

On 17 Jun 2012, at 12:06am, Etienne  wrote:

> Is there a trick (in the sys. libraries mentioned above, or through the win32 
> C API) for changing the way the FPU handles (long) doubles?

You're at tricky low level detail now.  Rounding and truncation modes used by 
chips which implement IEEE754 are often carefully set by compiler writers to 
get the results they want.  If you mess with the settings they've chosen, you 
can get unexpected results in other apps which were previously working 
correctly.

Ideally, you write your software so that differences in the 15th decimal place 
don't matter to you.  If you want two platforms to give identical results you 
use integer arithmetic.  It really depends on what kind of application you're 
writing (scientific, financial) or what your numbers actually represent.

It's discovering and caring about this sort of thing that separates out the 
professional programmer from the someone who shouldn't be paid for programming.

I do appreciate your thanks, by the way.

Simon.
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] VERY weird rounding error

2012-06-16 Thread Etienne
If ever I forget later, I would like to thank you guys (esp. Simon, Dominique, 
Keith and Jay) for the time you spend on this issue.

Your idea of dumping the memory at &realvalue was a very good idea, Simon.

You were right: "realvalue" values are already slightly different (2 less 
significant bytes of the 10-bytes equ. string) after the first iteration (i.e. 
realvalue*=0.1) of the "while" loop (sqlite3.c:19911), while they are still 
byte-to-byte identical at sqlite3.c:19908.

I use exactly the same byte code (i.e. the same sqlite3.o module), Keith.

So I summarize the situation:
realvalue * 0.1 = res1 in sqlite3.o linked to shell.o
realvalue * 0.1 = res2 in sqlite3.o linked to JSDB  - with res1!=res2!!

The JSDB win32 executable is built like this:

gcc.exe -static-libgcc -o jsdb.exe -mconsole -mwindows -mole obj\*.o  
obj\jsdb.coff  -lole32 -lws2_32 -lodbc32 -loleaut32 -lmapi32 -lcomdlg32 -luuid 
-lwinmm -static -lstdc++ 

while I simply build the SQLite exec with "gcc -o SQLite.exe sqlite3.o shell.o".

Is there a trick (in the sys. libraries mentioned above, or through the win32 C 
API) for changing the way the FPU handles (long) doubles?


Etienne
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-16 Thread Jay A. Kreibich
On Sat, Jun 16, 2012 at 02:00:27PM -0600, Keith Medcalf scratched on the wall:
> 
> Found the problem.
> 
> At sqlite3.c 19883:
>   if( precision<0 ) precision = 6;  /* Set default precision */
> 
> precision has a value of 15.  It should be 14 or less.  Don't know
> where it is getting this value from however.

  If by "this value" you mean the 6, that's the default precision for
  "%f" conversion in the printf() family of functions.

   -j

-- 
Jay A. Kreibich < J A Y  @  K R E I B I.C H >

"Intelligence is like underwear: it is important that you have it,
 but showing it to the wrong people has the tendency to make them
 feel uncomfortable." -- Angela Johnson
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-16 Thread Keith Medcalf

Found the problem.

At sqlite3.c 19883 if( precision<0 ) precision = 6; /* Set default 
precision */

precision has a value of 15.  It should be 14 or less.  Don't know where it is 
getting this value from however.



---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org


> -Original Message-
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of Keith Medcalf
> Sent: Saturday, 16 June, 2012 13:28
> To: General Discussion of SQLite Database
> Subject: Re: [sqlite] VERY weird rounding error
> 
> 
> Are you using the "same machine code" or merely "the same source code"?
> 
> The sqlite3 shell.c always asks for the results back converted to text.
> 
> Does your "other" shell ask for the results as "text" or as a double?
> 
> ...>python
> Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on
> win32
> Type "help", "copyright", "credits" or "license" for more information.
> >>> import apsw
> >>> import apswrow
> >>> import math
> >>> db = apsw.Connection(':memory:')
> >>> cr = db.cursor()
> >>> r1 = cr.execute('select 0.1 as double;').next()
> >>> r2 = cr.execute('select cast(0.1 as text) as textval;').next()
> 
> >>> r1
> Row(double=0.1)
> 
> >>> type(r1[0])
> 
> 
> >>> math.frexp(r1[0])
> (0.7628639221191407, 17)
> 
> >>> math.frexp(float('0.1'))
> (0.7628639221191407, 17)
> 
> >>> r2
> Row(textval=u'0.11')
> >>> type(r2[0])
> 
> 
> >>> math.frexp(float(r2[0]))
> (0.7628639221191413, 17)
> 
> ...>sqlite3d
> SQLite version 3.7.13 2012-06-11 02:05:22
> Enter ".help" for instructions
> Enter SQL statements terminated with a ";"
> sqlite> select 0.1;
> 0.11
> sqlite> select cast(0.1 as double);
> 0.11
> sqlite> select cast(0.1 as text);
> 0.11
> sqlite> select 0.11;
> 0.11
> 
> My conclusion is that the conversion from floating point to text in the
> SQLite database engine is inexact and designed as a convenience function
> only.  However, it is consistent. My recommendation would be that if you want
> "text" then use "text" everywhere.  If you want floating point, then use
> floating point everywhere.  You should not expect that wild conversions
> should produce the results you want.
> 
> ---
> ()  ascii ribbon campaign against html e-mail
> /\  www.asciiribbon.org
> 
> 
> > -Original Message-
> > From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> > boun...@sqlite.org] On Behalf Of Etienne
> > Sent: Saturday, 16 June, 2012 11:32
> > To: General Discussion of SQLite Database
> > Subject: [sqlite] VERY weird rounding error
> >
> > Hi Simon,
> >
> > Once again, I really do not care of the accuracy.
> >
> > I KNOW 0.1 CAN NOT BE STORED EXACTLY IN A REAL VARIABLE.
> >
> > I just try to figure out why the SAME CODE (sqlite3 library) with the SAME
> > INPUT gives DIFFERENT RESULTS (no matter how accurate/exact they
> individually
> > are!) when linked to different shells.
> >
> >
> > Etienne
> >
> >
> > - Original message -
> > From: Simon Slavin 
> > To: General Discussion of SQLite Database 
> > Subject: Re: [sqlite] VERY weird rounding error: details
> > Date: Sat, 16 Jun 2012 18:13:29 +0100
> >
> >
> > On 16 Jun 2012, at 5:41pm, Etienne  wrote:
> >
> > > 19913:   realvalue *= 0.1;
> >
> > This operation cannot be correctly executed while holding the value in a
> real
> > variable.  You will get inconsistent results.  Please read the reference I
> > gave earlier for an explanation of why it is pointless trying to get
> perfect
> > accuracy while handling a value of 0.1 in a real variable.
> >
> > Simon.
> > ___
> > sqlite-users mailing list
> > sqlite-users@sqlite.org
> > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
> > ___
> > sqlite-users mailing list
> > sqlite-users@sqlite.org
> > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
> 
> 
> 
> ___
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users



___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-16 Thread Keith Medcalf

Are you using the "same machine code" or merely "the same source code"?

The sqlite3 shell.c always asks for the results back converted to text.

Does your "other" shell ask for the results as "text" or as a double?

...>python
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on 
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import apsw
>>> import apswrow
>>> import math
>>> db = apsw.Connection(':memory:')
>>> cr = db.cursor()
>>> r1 = cr.execute('select 0.1 as double;').next()
>>> r2 = cr.execute('select cast(0.1 as text) as textval;').next()

>>> r1
Row(double=0.1)

>>> type(r1[0])


>>> math.frexp(r1[0])
(0.7628639221191407, 17)

>>> math.frexp(float('0.1'))
(0.7628639221191407, 17)

>>> r2
Row(textval=u'0.11')
>>> type(r2[0])


>>> math.frexp(float(r2[0]))
(0.7628639221191413, 17)

...>sqlite3d
SQLite version 3.7.13 2012-06-11 02:05:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select 0.1;
0.11
sqlite> select cast(0.1 as double);
0.11
sqlite> select cast(0.1 as text);
0.11
sqlite> select 0.11;
0.11

My conclusion is that the conversion from floating point to text in the SQLite 
database engine is inexact and designed as a convenience function only.  
However, it is consistent. My recommendation would be that if you want "text" 
then use "text" everywhere.  If you want floating point, then use floating 
point everywhere.  You should not expect that wild conversions should produce 
the results you want.

---
()  ascii ribbon campaign against html e-mail
/\  www.asciiribbon.org


> -Original Message-
> From: sqlite-users-boun...@sqlite.org [mailto:sqlite-users-
> boun...@sqlite.org] On Behalf Of Etienne
> Sent: Saturday, 16 June, 2012 11:32
> To: General Discussion of SQLite Database
> Subject: [sqlite] VERY weird rounding error
> 
> Hi Simon,
> 
> Once again, I really do not care of the accuracy.
> 
> I KNOW 0.1 CAN NOT BE STORED EXACTLY IN A REAL VARIABLE.
> 
> I just try to figure out why the SAME CODE (sqlite3 library) with the SAME
> INPUT gives DIFFERENT RESULTS (no matter how accurate/exact they individually
> are!) when linked to different shells.
> 
> 
> Etienne
> 
> 
> - Original message -
> From: Simon Slavin 
> To: General Discussion of SQLite Database 
> Subject: Re: [sqlite] VERY weird rounding error: details
> Date: Sat, 16 Jun 2012 18:13:29 +0100
> 
> 
> On 16 Jun 2012, at 5:41pm, Etienne  wrote:
> 
> > 19913:   realvalue *= 0.1;
> 
> This operation cannot be correctly executed while holding the value in a real
> variable.  You will get inconsistent results.  Please read the reference I
> gave earlier for an explanation of why it is pointless trying to get perfect
> accuracy while handling a value of 0.1 in a real variable.
> 
> Simon.
> ___
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
> ___
> sqlite-users mailing list
> sqlite-users@sqlite.org
> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users



___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-16 Thread Simon Slavin

On 16 Jun 2012, at 6:32pm, Etienne  wrote:

> Once again, I really do not care of the accuracy.
> 
> I KNOW 0.1 CAN NOT BE STORED EXACTLY IN A REAL VARIABLE.

I am unsurprised to find that your decimal strings are different after the 11th 
decimal place because your REAL values are not stored to 15 decimal places, and 
the calculations done with the numbers stored as REAL are not accurate to a 
precision of 10^-15.  Your number

0.901029468

involves a calculation involving the number

999.901029468

which has 20 decimal digits.  Calculations performed on Double-lenght REAL 
numbers are accurate only to 15 decimal digits.  Anything after that is just 
noise and can be ignored.  It doesn't matter what shows, because the programmer 
should never be showing the number to that much precision.

You posted

>>> Please note that the "realvalue" variable has identical values at the first 
>>> loop pass.


You have no way of knowing that.  You are seeing the value converted into a 
text string in an attempt to show it in decimal.  For all you know, the values 
are different, but they're being shown as the same text string because the 
difference is lost after the last digit.

There's no simple way to find out where the values are becoming different 
unless you dump the piece of memory the values are being stored in.  Do the 
calculation realvalue-999 in your code, store the resulting value in a 
variable, and dump the piece of memory that values is stored in (preferably as 
binary, but hexadecimal is acceptable).  Then look at the results from your two 
environments and see whether they're the same.

Your different maths libraries may do any of the following

1) turn your string '0.1' into different bit patterns, in order to store it as 
a binary value
2) do the same calculations but get different results because they round the 
right-hand bits differently
3) turn the same binary value into a different text string, when you ask to see 
the results in decimal.

This can happen
in different programming languages,
or in the same program compiled by two different compilers,
or in the same program compiled by the same compiler for two different 
platforms,
or in the same object code running on two identical platforms except for them 
having different CPUs,
or on identical platforms set to do rounding differently.

>From what I see, one of your programs is a C program and the other runs under 
>JSDB, whatever that is.  But you've now introduced another complication 
>because you're using the binary-to-decimal routines in gdb to show the results 
>as decimal, so instead of two environments you now have three.  Even if 
>they're both using the same IEEE754 algorithms You have no idea what rounding 
>mode each library uses.

For at least 50 years we've known that if you see a computer spit out a decimal 
number like

0.1 [lots of zeros here] 82734766

anything after the long line of zeros is rubbish.  It's perfectly predictable 
-- if you understand how your CPU does maths -- but it's not important.  
Because we know that storing values like 0.1 in a REAL variable will lead to 
that sort of thing because they cannot be stored accurately so it will happen 
every time.

Simon.
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error

2012-06-16 Thread Dominique Pellé
Etienne  wrote:

> Hi Simon,
>
> Once again, I really do not care of the accuracy.
>
> I KNOW 0.1 CAN NOT BE STORED EXACTLY IN A REAL VARIABLE.
>
> I just try to figure out why the SAME CODE (sqlite3 library) with the SAME 
> INPUT gives DIFFERENT RESULTS (no matter how accurate/exact they individually 
> are!) when linked to different shells.
>
>
> Etienne


The compiler may not produce strict IEEE-754 floating point
computations: trade off between optimizations and strict
conformance. Floating registers registers have more bits
than double IEEE 754 (80 bit registers, i.e. more accuracy
than double 64 bits). So strict conformance to IEEE would be
not not only slower but can also be less accurate.

Now if you need strict conformance to IEEE-754, you
can give options to the compiler.  Try compiling with
gcc option -ffloat-store for example. There might be
other relevant options. Also turn off optimizations (-O0).

Some links:

http://stackoverflow.com/questions/7295861/enabling-strict-floating-point-mode-in-gcc
http://stackoverflow.com/questions/982421/how-to-write-portable-floating-point-arithmetic-in-c/

Regards
-- Dominique
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] VERY weird rounding error

2012-06-16 Thread Etienne
Hi Simon,

Once again, I really do not care of the accuracy.

I KNOW 0.1 CAN NOT BE STORED EXACTLY IN A REAL VARIABLE.

I just try to figure out why the SAME CODE (sqlite3 library) with the SAME 
INPUT gives DIFFERENT RESULTS (no matter how accurate/exact they individually 
are!) when linked to different shells.


Etienne


- Original message -
From: Simon Slavin 
To: General Discussion of SQLite Database 
Subject: Re: [sqlite] VERY weird rounding error: details
Date: Sat, 16 Jun 2012 18:13:29 +0100


On 16 Jun 2012, at 5:41pm, Etienne  wrote:

> 19913:   realvalue *= 0.1;

This operation cannot be correctly executed while holding the value in a real 
variable.  You will get inconsistent results.  Please read the reference I gave 
earlier for an explanation of why it is pointless trying to get perfect 
accuracy while handling a value of 0.1 in a real variable.

Simon.
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


Re: [sqlite] VERY weird rounding error: details

2012-06-16 Thread Simon Slavin

On 16 Jun 2012, at 5:41pm, Etienne  wrote:

> 19913:   realvalue *= 0.1;

This operation cannot be correctly executed while holding the value in a real 
variable.  You will get inconsistent results.  Please read the reference I gave 
earlier for an explanation of why it is pointless trying to get perfect 
accuracy while handling a value of 0.1 in a real variable.

Simon.
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users


[sqlite] VERY weird rounding error: details

2012-06-16 Thread Etienne
Hi all,

The "0.1 case" is still a mystery!

For clarity reasons, I have expanded line 19911 of sqlite3.c (v3.7.13)


19909: while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
19910: while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
19911: while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
19912: while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
19913: while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }

as:

19909: while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
19910: while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
19911: while( realvalue>=10.0 && exp<=350 )
19912:   {
19913:   realvalue *= 0.1;
19914:   exp++;
19915:   }
19916: while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
19917: while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }


No other modification.

SQLite3.c is compiled (gcc -c -g sqlite3.c) with default options ONE TIME ONLY.

(Env: Int. Core i5, Win7 Pro/32, gcc 4.5, gdb 7.2) 

The same object module is linked to shell.o (for SQLite) and to JSDB.

SQLite is then launched under GDB (run NUL "select 0.1;", breakpoint set up 
accordingly).

The debugging session looks like:


(...)
(gdb) print realvalue-0
$6 = 0.100582077
(gdb) n
19913   realvalue *= 0.1;
(gdb) print realvalue-0
$7 = 0.100582077
(gdb) n
19914   exp++;
(gdb) print realvalue-
$8 = 0.0102037268
(gdb) n
19913   realvalue *= 0.1;
(gdb) print realvalue-
$9 = 0.0102037268
(gdb) n
19914   exp++;
(gdb) print realvalue-999
$10 = 0.901018099  <--
(gdb)
(...)


JSDB run in the same environment with the matching input:

js>var db = new SQLite();
js>db.exec("select 0.1",function(r){writeln(r)});

Here is a piece of the debugging session (same breakpoint):


(...)
(gdb) print realvalue-0
$4 = 0.100582077
(gdb) n
19913   realvalue *= 0.1;
(gdb) print realvalue-0
$5 = 0.100582077
(gdb) n
19914   exp++;
(gdb) print realvalue-
$6 = 0.0102037268
(gdb) n
19913   realvalue *= 0.1;
(gdb) print realvalue-
$7 = 0.0102037268
(gdb) n
19914   exp++;
(gdb) print realvalue-999
$8 = 0.901029468   <--
(gdb)
(...)


Please note that the "realvalue" variable has identical values at the first 
loop pass.

They only start diverging (29468/18099 = +/-60%) from the second pass!

This divergence leads to a rounding error in the second case (JSDB), while 
SQLite(shell) properly displays the ("faked") result.

So same input, same byte code... and different results! Who the heck said IT is 
determinist?

Does anybody figure out the reason of the difference?

Thanks in advance.


Etienne
___
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users