/ Check-in [ea0e3282]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:better handling of exponential notation (CVS 145)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:ea0e32828f5643eeb00b216a287d14f4826ddf2d
User & Date: drh 2000-09-14 01:21:10
Context
2000-09-14
01:25
Version 1.0.5 (CVS 495) check-in: 84839d87 user: drh tags: trunk
01:21
better handling of exponential notation (CVS 145) check-in: ea0e3282 user: drh tags: trunk
2000-08-28
16:25
Version 1.0.4 (CVS 496) check-in: 92346e00 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to VERSION.

     1         -1.0.4
            1  +1.0.5

Changes to src/util.c.

    22     22   **
    23     23   *************************************************************************
    24     24   ** Utility functions used throughout sqlite.
    25     25   **
    26     26   ** This file contains functions for allocating memory, comparing
    27     27   ** strings, and stuff like that.
    28     28   **
    29         -** $Id: util.c,v 1.14 2000/07/31 11:57:37 drh Exp $
           29  +** $Id: util.c,v 1.15 2000/09/14 01:21:10 drh Exp $
    30     30   */
    31     31   #include "sqliteInt.h"
    32     32   #include <stdarg.h>
    33     33   #include <ctype.h>
    34     34   
    35     35   #ifdef MEMORY_DEBUG
    36     36   
................................................................................
   545    545       }
   546    546       case 5: {
   547    547         result = cb - ca;
   548    548       };
   549    549     }
   550    550     return result;
   551    551   }
          552  +
          553  +/*
          554  +** Do a comparison of pure numerics.  If either string is not a pure
          555  +** numeric, then return 0.  Otherwise return 1 and set *pResult to be
          556  +** negative, zero or positive if the first string are numerially less than
          557  +** equal to, or greater than the second.
          558  +*/
          559  +static int privateCompareNum(const char *a, const char *b, int *pResult){
          560  +  char *endPtr;
          561  +  double rA, rB;
          562  +  int isNumA, isNumB;
          563  +  if( isdigit(*a) || ((*a=='-' || *a=='+') && isdigit(a[1])) ){
          564  +    rA = strtod(a, &endPtr);
          565  +    isNumA = *endPtr==0;
          566  +  }else{
          567  +    isNumA = 0;
          568  +  }
          569  +  if( isdigit(*b) || ((*b=='-' || *b=='+') && isdigit(b[1])) ){
          570  +    rB = strtod(b, &endPtr);
          571  +    isNumB = *endPtr==0;
          572  +  }else{
          573  +    isNumB = 0;
          574  +  }
          575  +  if( isNumB==0 && isNumA==0 ) return 0;
          576  +  if( isNumA!=isNumB ){
          577  +    *pResult =  isNumA - isNumB;
          578  +  }else if( rA<rB ){
          579  +    *pResult = -1;
          580  +  }else if( rA>rB ){
          581  +    *pResult = 1;
          582  +  }else{
          583  +    *pResult = 0;
          584  +  }
          585  +  return 1;
          586  +}
   552    587   
   553    588   /* This comparison routine is what we use for comparison operations
   554    589   ** in an SQL expression.  (Ex:  name<'Hello' or value<5).  Compare two
   555    590   ** strings.  Use case only as a tie-breaker.  Numbers compare in
   556    591   ** numerical order.
   557    592   */
   558    593   int sqliteCompare(const char *atext, const char *btext){
   559    594     int result;
   560         -  result = privateStrCmp(atext, btext, 0);
   561         -  if( result==0 ) result = privateStrCmp(atext, btext, 1);
          595  +  if( !privateCompareNum(atext, btext, &result) || result==0 ){
          596  +    result = privateStrCmp(atext, btext, 0);
          597  +    if( result==0 ) result = privateStrCmp(atext, btext, 1);
          598  +  }
   562    599     return result;
   563    600   }
   564    601   
   565    602   /*
   566    603   ** If you compile just this one file with the -DTEST_COMPARE=1 option,
   567    604   ** it generates a program to test the comparisons routines.  
   568    605   */
................................................................................
   569    606   #ifdef TEST_COMPARE
   570    607   #include <stdlib.h>
   571    608   #include <stdio.h>
   572    609   int sortCmp(const char **a, const char **b){
   573    610     return sqliteCompare(*a, *b);
   574    611   }
   575    612   int main(int argc, char **argv){
   576         -  int i, j, k, n;
          613  +  int i, j, k, n, cnt;
   577    614     static char *azStr[] = {
   578    615        "abc", "aBc", "abcd", "aBcd", 
   579         -     "123", "124", "1234", "-123", "-124", "-1234", 
          616  +     "123", "124", "1234", "-123", "-124", "-1234", "+124",
   580    617        "123.45", "123.456", "123.46", "-123.45", "-123.46", "-123.456", 
   581    618        "x9", "x10", "x-9", "x-10", "X9", "X10",
          619  +     "1.234e+02", "+123", "1.23E2", "1.2345e+2", "-1.2345e2", "+w"
   582    620     };
   583    621     n = sizeof(azStr)/sizeof(azStr[0]);
   584    622     qsort(azStr, n, sizeof(azStr[0]), sortCmp);
   585    623     for(i=0; i<n; i++){
   586    624       printf("%s\n", azStr[i]);
   587    625     }
   588    626     printf("Sanity1...");
   589    627     fflush(stdout);
          628  +  cnt = 0;
   590    629     for(i=0; i<n-1; i++){
   591    630       char *a = azStr[i];
   592    631       for(j=i+1; j<n; j++){
   593    632         char *b = azStr[j];
   594    633         if( sqliteCompare(a,b) != -sqliteCompare(b,a) ){
   595    634           printf("Failed!  \"%s\" vs \"%s\"\n", a, b);
   596    635           i = j = n;
   597    636         }
          637  +      cnt++;
   598    638       }
   599    639     }
   600    640     if( i<n ){
   601         -    printf(" OK\n");
          641  +    printf(" OK (%d)\n", cnt);
          642  +  }
          643  +  printf("Sanity2...");
          644  +  fflush(stdout);
          645  +  cnt = 0;
          646  +  for(i=0; i<n; i++){
          647  +    char *a = azStr[i];
          648  +    for(j=0; j<n; j++){
          649  +      char *b = azStr[j];
          650  +      for(k=0; k<n; k++){
          651  +        char *c = azStr[k];
          652  +        int x1, x2, x3, success;
          653  +        x1 = sqliteCompare(a,b);
          654  +        x2 = sqliteCompare(b,c);
          655  +        x3 = sqliteCompare(a,c);
          656  +        if( x1==0 ){
          657  +          success = x2==x3;
          658  +        }else if( x1<0 ){
          659  +          success = (x2<=0 && x3<=0) || x2>0;
          660  +        }else{
          661  +          success = (x2>=0 && x3>=0) || x2<0;
          662  +        }
          663  +        if( !success ){
          664  +          printf("Failed!  \"%s\" vs \"%s\" vs \"%s\"\n", a, b, c);
          665  +          i = j = k = n+1;
          666  +        }
          667  +        cnt++;
          668  +      }
          669  +    }
          670  +  }
          671  +  if( i<n+1 ){
          672  +    printf(" OK (%d)\n", cnt);
   602    673     }
   603    674     return 0;
   604    675   }
   605    676   #endif
   606    677   
   607    678   /*
   608    679   ** This routine is used for sorting.  Each key is a list of one or more

Changes to src/vdbe.c.

    37     37   ** inplicit conversion from one type to the other occurs as necessary.
    38     38   ** 
    39     39   ** Most of the code in this file is taken up by the sqliteVdbeExec()
    40     40   ** function which does the work of interpreting a VDBE program.
    41     41   ** But other routines are also provided to help in building up
    42     42   ** a program instruction by instruction.
    43     43   **
    44         -** $Id: vdbe.c,v 1.40 2000/08/28 16:22:00 drh Exp $
           44  +** $Id: vdbe.c,v 1.41 2000/09/14 01:21:10 drh Exp $
    45     45   */
    46     46   #include "sqliteInt.h"
    47     47   #include <unistd.h>
    48     48   
    49     49   /*
    50     50   ** SQL is translated into a sequence of instructions to be
    51     51   ** executed by a virtual machine.  Each instruction is an instance
................................................................................
   543    543   */
   544    544   #define Stringify(P,I) \
   545    545      ((P->aStack[I].flags & STK_Str)==0 ? hardStringify(P,I) : 0)
   546    546   static int hardStringify(Vdbe *p, int i){
   547    547     char zBuf[30];
   548    548     int fg = p->aStack[i].flags;
   549    549     if( fg & STK_Real ){
   550         -    sprintf(zBuf,"%g",p->aStack[i].r);
          550  +    sprintf(zBuf,"%.15g",p->aStack[i].r);
   551    551     }else if( fg & STK_Int ){
   552    552       sprintf(zBuf,"%d",p->aStack[i].i);
   553    553     }else{
   554    554       p->zStack[i] = "";
   555    555       p->aStack[i].n = 1;
   556    556       p->aStack[i].flags |= STK_Str;
   557    557       return 0;

Changes to test/expr.test.

    19     19   #   drh@hwaci.com
    20     20   #   http://www.hwaci.com/drh/
    21     21   #
    22     22   #***********************************************************************
    23     23   # This file implements regression tests for SQLite library.  The
    24     24   # focus of this file is testing expressions.
    25     25   #
    26         -# $Id: expr.test,v 1.8 2000/06/16 20:51:26 drh Exp $
           26  +# $Id: expr.test,v 1.9 2000/09/14 01:21:11 drh Exp $
    27     27   
    28     28   set testdir [file dirname $argv0]
    29     29   source $testdir/tester.tcl
    30     30   
    31     31   # Create a table to work with.
    32     32   #
    33     33   execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)}
................................................................................
    76     76   test_expr expr-1.35 {i1=1, i2=2} {i1-i2=-1} {1}
    77     77   test_expr expr-1.36 {i1=1, i2=0} {not i1} {0}
    78     78   test_expr expr-1.37 {i1=1, i2=NULL} {not i2} {1}
    79     79   
    80     80   test_expr expr-2.1 {r1=1.23, r2=2.34} {r1+r2} 3.57
    81     81   test_expr expr-2.2 {r1=1.23, r2=2.34} {r1-r2} -1.11
    82     82   test_expr expr-2.3 {r1=1.23, r2=2.34} {r1*r2} 2.8782
    83         -test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641
    84         -test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90244
           83  +test_expr expr-2.4 {r1=1.23, r2=2.34} {r1/r2} 0.525641025641026
           84  +test_expr expr-2.5 {r1=1.23, r2=2.34} {r2/r1} 1.90243902439024
    85     85   test_expr expr-2.6 {r1=1.23, r2=2.34} {r2<r1} 0
    86     86   test_expr expr-2.7 {r1=1.23, r2=2.34} {r2<=r1} 0
    87     87   test_expr expr-2.8 {r1=1.23, r2=2.34} {r2>r1} 1
    88     88   test_expr expr-2.9 {r1=1.23, r2=2.34} {r2>=r1} 1
    89     89   test_expr expr-2.10 {r1=1.23, r2=2.34} {r2!=r1} 1
    90     90   test_expr expr-2.11 {r1=1.23, r2=2.34} {r2=r1} 0
    91     91   test_expr expr-2.12 {r1=1.23, r2=2.34} {r2<>r1} 1

Changes to www/changes.tcl.

    12     12   }
    13     13   
    14     14   
    15     15   proc chng {date desc} {
    16     16     puts "<DT><B>$date</B></DT>"
    17     17     puts "<DD><P><UL>$desc</UL></P></DD>"
    18     18   }
           19  +
           20  +chng {2000 Sep 13 (Version 1.0.5)} {
           21  +<li>Changed the print format for floating point values from "%g" to "%.15g".
           22  +    </li>
           23  +<li>Changed the comparison function so that numbers in exponential notation
           24  +    (ex: 1.234e+05) sort in numerical order.</li>
           25  +}
    19     26   
    20     27   chng {2000 Aug 28 (Version 1.0.4)} {
    21     28   <li>Added functions <b>length()</b> and <b>substr()</b>.</li>
    22     29   <li>Fix a bug in the <b>sqlite</b> shell program that was causing
    23     30       a coredump when the output mode was "column" and the first row
    24     31       of data contained a NULL.</li>
    25     32   }