/ 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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 641b2d210541b4d5a1a9e57d7dcf5ce5dfd7ff4d2dc6277ba0582869f48fc946
User & Date: drh 2019-05-24 22:58:16
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
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/printf.c.

95
96
97
98
99
100
101






102
103
104
105
106
107
108
...
513
514
515
516
517
518
519
520




521

522
523
524
525
526
527
528

  /* 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
................................................................................
          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;
        }







>
>
>
>
>
>







 







|
>
>
>
>
|
>







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539

  /* 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
................................................................................
          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