SQLite

Check-in [641b2d2105]
Login

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

Overview
Comment:Improvements to rounding behavior in the round() and printf() functions.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 641b2d210541b4d5a1a9e57d7dcf5ce5dfd7ff4d2dc6277ba0582869f48fc946
User & Date: drh 2019-05-24 22:58:16.438
Context
2019-05-25
00:17
Disable the new rounding tests on systems without long double support. (check-in: ed250b4e18 user: drh tags: trunk)
2019-05-24
22:58
Improvements to rounding behavior in the round() and printf() functions. (check-in: 641b2d2105 user: drh tags: trunk)
11:55
Fix an fts5 segfault that could occur after parsing a corrupt structure record. (check-in: 600daa9c27 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/printf.c.
95
96
97
98
99
100
101






102
103
104
105
106
107
108

  /* All the rest are undocumented and are for internal use only */
  {  'T',  0, 0, etTOKEN,      0,  0 },
  {  'S',  0, 0, etSRCLIST,    0,  0 },
  {  'r', 10, 1, etORDINAL,    0,  0 },
};







/*
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** "*val" is a double such that 0.1 <= *val < 10.0







>
>
>
>
>
>







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

  /* All the rest are undocumented and are for internal use only */
  {  'T',  0, 0, etTOKEN,      0,  0 },
  {  'S',  0, 0, etSRCLIST,    0,  0 },
  {  'r', 10, 1, etORDINAL,    0,  0 },
};

/* Floating point constants used for rounding */
static const double arRound[] = {
  5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
  5.0e-06, 5.0e-07, 5.0e-08, 5.0e-09, 5.0e-10,
};

/*
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** "*val" is a double such that 0.1 <= *val < 10.0
513
514
515
516
517
518
519
520


521



522
523
524
525
526
527
528
          realvalue = -realvalue;
          prefix = '-';
        }else{
          prefix = flag_prefix;
        }
        if( xtype==etGENERIC && precision>0 ) precision--;
        testcase( precision>0xfff );
        for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}


        if( xtype==etFLOAT ) realvalue += rounder;



        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
        exp = 0;
        if( sqlite3IsNaN((double)realvalue) ){
          bufpt = "NaN";
          length = 3;
          break;
        }







|
>
>
|
>
>
>







519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
          realvalue = -realvalue;
          prefix = '-';
        }else{
          prefix = flag_prefix;
        }
        if( xtype==etGENERIC && precision>0 ) precision--;
        testcase( precision>0xfff );
        idx = precision & 0xfff;
        rounder = arRound[idx%10];
        while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; }
        if( xtype==etFLOAT ){
          if( precision<17) rounder += realvalue*2.0e-16;
          realvalue += rounder;
        }
        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
        exp = 0;
        if( sqlite3IsNaN((double)realvalue) ){
          bufpt = "NaN";
          length = 3;
          break;
        }
Added test/round1.test.


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 2019-05-24
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# Test cases for rounding behavior of floating point values.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix round1

expr srand(0)
unset -nocomplain iTest
for {set iTest 1} {$iTest<=10000} {incr iTest} {
   set x1 [expr int(rand()*100000)]
   set x2 [expr int(rand()*100000)+1000*int(rand()*10000)]
   set n [expr int(rand()*8)+1]
   set x3 [string range [format %09d $x2] [expr {9-$n}] end]
   set r $x1.$x3
   set ans [string trimright $r 0]
   if {[string match *. $ans]} {set ans ${ans}0}
   do_test $iTest/$n/${r}4=>$ans {
     set x [db one "SELECT round(${r}4,$n)"]
   } $ans
   set x4 [string range [format %09d [expr {$x2+1}]] [expr {9-$n}] end]
   if {[string trim $x3 9]==""} {incr x1}
   set r2 $x1.$x4
   set ans [string trimright $r2 0]
   if {[string match *. $ans]} {set ans ${ans}0}
   do_test $iTest/$n/${r}5=>$ans {
     set x [db one "SELECT round(${r}5,$n)"]
   } $ans
}

finish_test