Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From 56af06fa12104a1f To 3dec4b35ecd68a4d
2024-06-11
| ||
14:36 | Change constant expressions to pre-computed constants, because apparently MSVC on ARM requires that. Forum thread 4feb1685cced0a8e. (check-in: 6c103aee6f user: drh tags: trunk) | |
2024-06-10
| ||
18:30 | The aggressive rounding behavior is now only accessible using the internal sqlite3MPrintf() function. The round() SQL function uses that internal function so it can access the aggressive rounding. But ordinary extensions and the format() SQL function cannot. Update: Superseded by round-up-2 branch (Closed-Leaf check-in: 3dec4b35ec user: drh tags: round-up) | |
18:10 | More aggressive rounding behavior for the round() function only. Format() still uses the classic behavior, and the same behavior exhibited by printf() in glibc. (check-in: a1b57288d7 user: drh tags: round-up) | |
14:31 | Change the rounding behavior of float point to decimal conversions such that if the next digit is 4 but the value is within one epsilon of the next digit being 5 and if the epsilon is small compared the number of digits to be rendered, then go ahead and round up anyhow, even though the correct behavior would be to round down. (check-in: 4a790d3b28 user: drh tags: round-up) | |
12:43 | Improved header comment on the sqlite3FpDecode() implementation. For the fpdecode() SQL function (available in debug builds only) limit the value of the third parameter (mxRound) to be positive. (check-in: 56af06fa12 user: drh tags: trunk) | |
2024-06-09
| ||
17:34 | Disable the omit-noop-join optimization when there are 64 or more terms in the ORDER BY clause. (check-in: 40de393979 user: drh tags: trunk) | |
Changes to src/func.c.
︙ | ︙ | |||
457 458 459 460 461 462 463 | ** otherwise use printf. */ if( r<-4503599627370496.0 || r>+4503599627370496.0 ){ /* The value has no fractional part so there is nothing to round */ }else if( n==0 ){ r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); }else{ | > | | | 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 | ** otherwise use printf. */ if( r<-4503599627370496.0 || r>+4503599627370496.0 ){ /* The value has no fractional part so there is nothing to round */ }else if( n==0 ){ r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5))); }else{ sqlite3 *db = sqlite3_context_db_handle(context); zBuf = sqlite3MPrintf(db,"%!.*f",n,r); if( zBuf==0 ){ sqlite3_result_error_nomem(context); return; } sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8); sqlite3DbFreeNN(db, zBuf); } sqlite3_result_double(context, r); } #endif /* ** Allocate nByte bytes of space using sqlite3Malloc(). If the |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | break; case etFLOAT: case etEXP: case etGENERIC: { FpDecode s; int iRound; int j; if( bArgList ){ realvalue = getDoubleArg(pArgList); }else{ realvalue = va_arg(ap,double); } if( precision<0 ) precision = 6; /* Set default precision */ #ifdef SQLITE_FP_PRECISION_LIMIT if( precision>SQLITE_FP_PRECISION_LIMIT ){ precision = SQLITE_FP_PRECISION_LIMIT; } #endif if( xtype==etFLOAT ){ iRound = -precision; }else if( xtype==etGENERIC ){ if( precision==0 ) precision = 1; iRound = precision; }else{ iRound = precision+1; } | > > > > > > | | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | break; case etFLOAT: case etEXP: case etGENERIC: { FpDecode s; int iRound; int j; int mx; if( bArgList ){ realvalue = getDoubleArg(pArgList); }else{ realvalue = va_arg(ap,double); } if( precision<0 ) precision = 6; /* Set default precision */ #ifdef SQLITE_FP_PRECISION_LIMIT if( precision>SQLITE_FP_PRECISION_LIMIT ){ precision = SQLITE_FP_PRECISION_LIMIT; } #endif if( xtype==etFLOAT ){ iRound = -precision; }else if( xtype==etGENERIC ){ if( precision==0 ) precision = 1; iRound = precision; }else{ iRound = precision+1; } if( flag_altform2 ){ mx = 26 + ((pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)!=0); }else{ mx = 16; } sqlite3FpDecode(&s, realvalue, iRound, mx); if( s.isSpecial ){ if( s.isSpecial==2 ){ bufpt = flag_zeropad ? "null" : "NaN"; length = sqlite3Strlen30(bufpt); break; }else if( flag_zeropad ){ s.z[0] = '9'; |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 | ** string is not an integer, just return 0. */ int sqlite3Atoi(const char *z){ int x = 0; sqlite3GetInt32(z, &x); return x; } /* ** Decode a floating-point value into an approximate decimal ** representation. ** ** If iRound<=0 then round to -iRound significant digits to the ** the left of the decimal point, or to a maximum of mxRound total ** significant digits. ** ** If iRound>0 round to min(iRound,mxRound) significant digits total. ** ** mxRound must be positive. ** ** The significant digits of the decimal representation are ** stored in p->z[] which is a often (but not always) a pointer ** into the middle of p->zBuf[]. There are p->n significant digits. ** The p->z[] array is *not* zero-terminated. */ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ int i; u64 v; int e, exp = 0; p->isSpecial = 0; p->z = p->zBuf; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | ** string is not an integer, just return 0. */ int sqlite3Atoi(const char *z){ int x = 0; sqlite3GetInt32(z, &x); return x; } /* ** z[] is the complete list of digits for a floating point conversion. ** The z[iRound] character is a 4. This routine checks to see if the ** iRound-1 character should be rounded up even though z[iRound] is not ** a 5. ** ** Return true if the 4 is followed by at least three 9s and all digits ** past the 4 are 9s out to the limit of precision. */ static SQLITE_NOINLINE int shouldRoundUp(const char *z, int n, int iRound){ int i; assert( z[iRound]=='4' ); for(i=iRound+1; i<n && z[i]=='9'; i++){} if( i<iRound+3 ) return 0; return i>15; } /* ** Decode a floating-point value into an approximate decimal ** representation. ** ** If iRound<=0 then round to -iRound significant digits to the ** the left of the decimal point, or to a maximum of mxRound total ** significant digits. ** ** If iRound>0 round to min(iRound,mxRound) significant digits total. ** ** mxRound must be positive. ** ** The significant digits of the decimal representation are ** stored in p->z[] which is a often (but not always) a pointer ** into the middle of p->zBuf[]. There are p->n significant digits. ** The p->z[] array is *not* zero-terminated. ** ** Rounding Behavior: ** ** (1) If the next digit is 3 or less, then truncate. Do not round. ** ** (2) If the next digit is 5 or more, then round up. ** ** (3) Round up if the next digit is a 4 followed by three or ** more 9 digits and all significant digits after the 4 are ** 9 and mxRound is 27. Otherwise truncate. ** ** Rule (3) is used by the built-in round() function to do more aggressive ** rounding so that things like round(0.15,1) will come out as 0.2 ** even though the stored value for 0.15 is really ** 0.1499999999999999944488848768742172978818416595458984375 and ought ** to round down to 0.1. Rule (3) is only applied if mxRound==27. ** And mxRound is only 27 if the internal sqlite3MPrintf() formatter is ** used and the "!" flag is included. */ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){ int i; u64 v; int e, exp = 0; p->isSpecial = 0; p->z = p->zBuf; |
︙ | ︙ | |||
1136 1137 1138 1139 1140 1141 1142 | p->n++; p->iDP++; } } if( iRound>0 && (iRound<p->n || p->n>mxRound) ){ char *z = &p->zBuf[i+1]; if( iRound>mxRound ) iRound = mxRound; | < | > > | > | | 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 | p->n++; p->iDP++; } } if( iRound>0 && (iRound<p->n || p->n>mxRound) ){ char *z = &p->zBuf[i+1]; if( iRound>mxRound ) iRound = mxRound; if( z[iRound]>='5' || (z[iRound]=='4' && mxRound>=27 && shouldRoundUp(z, p->n, iRound)) ){ int j = iRound-1; while( 1 /*exit-by-break*/ ){ z[j]++; if( z[j]<='9' ) break; z[j] = '0'; if( j==0 ){ p->z[i--] = '1'; iRound++; p->iDP++; break; }else{ j--; } } } p->n = iRound; } p->z = &p->zBuf[i+1]; assert( i+p->n < sizeof(p->zBuf) ); while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; } } /* ** Try to convert z into an unsigned 32-bit integer. Return true on |
︙ | ︙ |
Added test/round2.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 42 43 | # 2024-06-10 # # 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. # #*********************************************************************** # # https://sqlite.org/forum/forumpost/c0753dfb2d5d7f75 # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix round2 load_static_extension db stmtrand do_execsql_test 1.1 { WITH RECURSIVE c(n) AS (VALUES(0) UNION ALL SELECT n+1 FROM c WHERE n<100000), r(a,b) AS MATERIALIZED (SELECT stmtrand()%100000, stmtrand()%100000 FROM c), f(x,y,n) AS ( SELECT CAST(format('%d.%d5',a,b) AS real), CAST(format('%d.%d6',a,b) AS real), length(format('%d',b)) FROM r) SELECT x, n, round(x,n), round(y,n) FROM f WHERE round(x,n)<>round(y,n); } {} do_execsql_test 1.2 { SELECT round(0.15,1); } 0.2 do_execsql_test 1.3 { SELECT round(0.14999999999999999,1); } 0.2 do_execsql_test 1.4 { SELECT round(0.1499999999999999944488848768742172978818416595458984375,1); } 0.2 finish_test |