]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
More aggressive rounding behavior for the round() function only.
authordrh <>
Mon, 10 Jun 2024 18:10:35 +0000 (18:10 +0000)
committerdrh <>
Mon, 10 Jun 2024 18:10:35 +0000 (18:10 +0000)
Format() still uses the classic behavior, and the same behavior exhibited
by printf() in glibc.

FossilOrigin-Name: a1b57288d7076cb9e26ac429f01e9264240d6af26243a195b2065cf667bb8bb6

manifest
manifest.uuid
src/func.c
src/printf.c
src/util.c

index 8d40a46dd4405f679abdfab99a464266943d891a..a1414b8c6df7d50fcb6c197000cd55f6c939a7bc 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Change\sthe\srounding\sbehavior\sof\sfloat\spoint\sto\sdecimal\sconversions\ssuch\sthat\nif\sthe\snext\sdigit\sis\s4\sbut\sthe\svalue\sis\swithin\sone\sepsilon\sof\sthe\snext\sdigit\nbeing\s5\sand\sif\sthe\sepsilon\sis\ssmall\scompared\sthe\snumber\sof\sdigits\sto\sbe\nrendered,\sthen\sgo\sahead\sand\sround\sup\sanyhow,\neven\sthough\sthe\scorrect\sbehavior\swould\sbe\sto\sround\sdown.
-D 2024-06-10T14:31:07.017
+C More\saggressive\srounding\sbehavior\sfor\sthe\sround()\sfunction\sonly.\nFormat()\sstill\suses\sthe\sclassic\sbehavior,\sand\sthe\ssame\sbehavior\sexhibited\nby\sprintf()\sin\sglibc.
+D 2024-06-10T18:10:35.427
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -708,7 +708,7 @@ F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
 F src/expr.c af9c9242be0df17280faf36c9810339de9df3d7a64ac8d33a5190a1400086ee5
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 852f93c0ef995e0c2b8983059a2b97151c194cc8259e21f5bc2b7ac508348c2a
-F src/func.c 1f61e32e7a357e615b5d2e774bee563761fce4f2fd97ecb0f72c33e62a2ada5f
+F src/func.c 42053720bb3bf4e4e06072f22c2cde4a0477961990a31c4887f3668f8cf4543b
 F src/global.c 61a419dd9e993b9be0f91de4c4ccf322b053eb829868e089f0321dd669be3b90
 F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
 F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
@@ -751,7 +751,7 @@ F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
 F src/pragma.c 52bfbf6dfd668b69b5eb9bd1186e3a67367c8453807150d6e75239229924f684
 F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
 F src/prepare.c d99931f45416652895e502328ca49fe782cfc4e1ebdcda13b3736d991ebf42ce
-F src/printf.c 8b250972305e14b365561be5117ed0fd364e4fd58968776df1ce64c6280b90f9
+F src/printf.c bdb1b615431486709f4a52149468b509a6f04ef5535716e3d05a12c7ddac6de0
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c 7e8d23ce7cdbfedf351a47e759f2722e8182ca10fd7580be43f4ce1f1a228145
 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
@@ -823,7 +823,7 @@ F src/trigger.c 0858f75818ed1580332db274f1032bcc5effe567cb132df5c5be8b1d800ca97f
 F src/update.c 732404a04d1737ef14bb6ec6b84f74edf28b3c102a92ae46b4855438a710efe7
 F src/upsert.c 2e60567a0e9e8520c18671b30712a88dc73534474304af94f32bb5f3ef65ac65
 F src/utf.c f23165685a67b4caf8ec08fb274cb3f319103decfb2a980b7cfd55d18dfa855e
-F src/util.c cedda44359c51d971557614216085c31d78ee7d23cc89400061c5433855aff64
+F src/util.c 6bd44646223215079588dcac46206c3200d5ba29b9866fabb94dc5a98973f971
 F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
 F src/vdbe.c b05777c3ff2ed7b9dfc347e7cdee18e371aa6811cef1fe83454691b0dbe2cc9f
 F src/vdbe.h c2d78d15112c3fc5ab87f5e8e0b75d2db1c624409de2e858c3d1aafb1650bb4f
@@ -2196,11 +2196,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 56af06fa12104a1fe119d7087746011183af053834eac72d0fb69f60d98054c6
-R d2547c87a8223548d3daae3e983f63e3
-T *branch * round-up
-T *sym-round-up *
-T -sym-trunk *
+P 4a790d3b28685f08bbb722057cd6a97aea08a2b2a6098562c6373fd3b5b7206c
+R 73295dcd1493f41c7a4fa684616e652f
 U drh
-Z fe023add6bc94c6c74f3cca88a0e7276
+Z 16d69236535ed95782490792d241c4e4
 # Remove this line to create a well-formed Fossil manifest.
index 79ca38fb04f070d0fc4deadba9be55af52ccf85d..41e392c7aa804e9abcf6d7355a21b40650303230 100644 (file)
@@ -1 +1 @@
-4a790d3b28685f08bbb722057cd6a97aea08a2b2a6098562c6373fd3b5b7206c
\ No newline at end of file
+a1b57288d7076cb9e26ac429f01e9264240d6af26243a195b2065cf667bb8bb6
\ No newline at end of file
index 8fcda11dc0b8c8200a36c2e0dcb97484666a34e7..ec1228bb75d2d30df1959f0651280a277c1bd557 100644 (file)
@@ -461,7 +461,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   }else if( n==0 ){ 
     r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5)));
   }else{
-    zBuf = sqlite3_mprintf("%!.*f",n,r);
+    zBuf = sqlite3_mprintf("%#!.*f",n,r);
     if( zBuf==0 ){
       sqlite3_result_error_nomem(context);
       return;
index c0dcc5d0fa1682b39f6727935a376d0a65142e8c..9640b0cac8883de4334bcb941b5b4c3937c68c2d 100644 (file)
@@ -503,7 +503,11 @@ void sqlite3_str_vappendf(
         }else{
           iRound = precision+1;
         }
-        sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
+        sqlite3FpDecode(&s, realvalue, iRound, 
+            flag_altform2 ? 26+flag_alternateform : 16);
+            /*                 ^^^^^^^^^^^^^^^^^^^--- Undocumented behavior:
+            ** When both '#' and '!' flags are present, the rounding behavior
+            ** is changed.  See "rule 3" in the sqlite3FpDecode docs. */
         if( s.isSpecial ){
           if( s.isSpecial==2 ){
             bufpt = flag_zeropad ? "null" : "NaN";
index fb25fa4b29138218946b2b41871f16f8a83fe666..e4c8159a3fc60328493292b642445258af52ecf5 100644 (file)
@@ -1012,15 +1012,20 @@ int sqlite3Atoi(const char *z){
 }
 
 /*
-** Return true if the first N characters of string z[] are '9'
+** 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 allNines(const char *z, int N){
+static SQLITE_NOINLINE int shouldRoundUp(const char *z, int n, int iRound){
   int i;
-  assert( N>0 );
-  for(i=0; i<N; i++){
-    if( z[i]!='9' ) return 0;
-  }
-  return 1;
+  assert( z[iRound]=='4' );
+  for(i=iRound+1; i<n && z[i]=='9'; i++){}
+  if( i<iRound+3 ) return 0;
+  return i>15;
 }
 
 /*
@@ -1053,7 +1058,13 @@ static SQLITE_NOINLINE int allNines(const char *z, int N){
 ** Rule (3) is 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.
+** to round down to 0.1.  Rule (3) is only applied if mxRound==27.
+**
+** This routine is normally only called from printf()/format().  In that
+** case, mxRound is usually 16 but is increased to 26 with the "!" flag.
+** Undocumented behavior:  mxRound is 27 with the "#" and "!" flags.  The
+** round() function uses this undocumented flag combination to activate
+** rounding rule (3).
 */
 void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
   int i;
@@ -1168,8 +1179,7 @@ void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
     char *z = &p->zBuf[i+1];
     if( iRound>mxRound ) iRound = mxRound;
     if( z[iRound]>='5'
-     || (z[iRound]=='4' && p->n>iRound+5
-                        && allNines(&z[iRound+1],p->n-iRound-3))
+     || (z[iRound]=='4' && mxRound>=27 && shouldRoundUp(z, p->n, iRound))
     ){
       int j = iRound-1;
       while( 1 /*exit-by-break*/ ){