SQLite Forum

function round() broken ?
Login

function round() broken ?

(1) By jmc (jmc123) on 2023-09-12 12:54:56 [link] [source]

SQlite 3.43.0 Windows 10

SELECT round(146.3599,1) 146.4

SELECT round(146.3599,2) 146.3599999999

Thanks

-jm

(2) By jose isaias cabrera (jicman) on 2023-09-12 13:28:01 in reply to 1 [link] [source]

In version 3.44.0 is fixed...

-- Loading resources from C:\Users\e608313/.sqliterc
SQLite version 3.44.0 2023-09-05 15:03:23
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> SELECT round(146.3599,1);
┌───────────────────┐
│ round(146.3599,1) │
├───────────────────┤
│ 146.4             │
└───────────────────┘
VM-steps: 9
Run Time: real 0.009 user 0.000000 sys 0.015625
sqlite> SELECT round(146.3599,2);
┌───────────────────┐
│ round(146.3599,2) │
├───────────────────┤
│ 146.36            │
└───────────────────┘
VM-steps: 9
Run Time: real 0.009 user 0.015625 sys 0.000000

(3) By Gunter Hick (gunter_hick) on 2023-09-12 13:28:18 in reply to 1 [link] [source]

SQLite version 3.43.0 2023-08-24 12:36:59
Welcome to the "fiddle" shell.

Enter ".help" for usage hints.
.nullvalue NULL
.headers on
round(142.3599,0)
142.0
round(142.3599,1)
142.4
round(142.3599,2)
142.36
round(142.3599,3)
142.36
round(142.3599,4)
142.3599

(4) By Richard Hipp (drh) on 2023-09-12 13:48:47 in reply to 1 [link] [source]

I'm unable to reproduce this problem. I get:

SELECT round(146.3599,1), round(146.3599,2);
┌───────────────────┬───────────────────┐
│ round(145.3599,1) │ round(145.3599,2) │
├───────────────────┼───────────────────┤
│ 145.4             │ 145.36            │
└───────────────────┴───────────────────┘

I tried this using MSVC builds of 3.43.0, both 64-bit and 32-bit. Same answer ever time.

(5) By jmc (jmc123) on 2023-09-12 14:14:15 in reply to 4 [link] [source]

Thanks all for your replies

Below are other examples on my PC (DELL computer Intel xeon):

round(123.12345,1) 123.1

round(123.12345,2) 123.12

round(123.12399,3) 123.124

round(123.12399,4) 123.124

round(146.36,1) 146.4

round(146.36,2) 146.35999999999999

??

What possible explanation ?

SELECT sqlite_source_id() 2023-08-24 12:36:59 0f80b798b3f4b81a7bb4233c58294edd0f1156f36b6ecf5ab8e83631d468778c

(6) By Larry Brasfield (larrybr) on 2023-09-12 14:31:02 in reply to 5 [link] [source]

round(146.36,2) 146.35999999999999


??

What possible explanation ?

Try this: SELECT round(146.36,2) - 146.36;

If you are still puzzled, read up on the limitations of floating point representation of real numbers. Or search through the never-ending posts here on that topic.

(7) By Richard Hipp (drh) on 2023-09-12 14:34:07 in reply to 5 [link] [source]

Are you using the official CLI, or are you using a 3rd-party tool? If the latter, I suggest the problem is in the 3rd-party tool that you are using.

(8) By jmc (jmc123) on 2023-09-12 14:38:15 in reply to 4 [source]

Further explorations make us believe it might be a compilation pb.

We don't compile the SQLite library ourself

We are trying to go in touch with the person who did the job

Sorry for the noise and false alarm

Thanks again

(9.1) Originally by Jocelyne (jocelyne-a) with edits by Richard Hipp (drh) on 2023-09-12 14:51:44 from 9.0 in reply to 1 [link] [source]

I am also encountering this issue in 3.43.1 on Mac

DROP TABLE IF EXISTS fakeTable;
CREATE TABLE IF NOT EXISTS fakeTable (id INTEGER PRIMARY KEY AUTOINCREMENT);
INSERT INTO fakeTable  DEFAULT VALUES;
SELECT ROUND(10.555, 2) FROM fakeTable;

Expected result: 10.56
Actual result: 10.55

Thanks.

(10) By Richard Hipp (drh) on 2023-09-12 14:55:31 in reply to 9.1 [link] [source]

SQLite uses the IEEE 754 binary64 format to represent floating point values. But 10.555 does not exist as a number in that format. The closest available number that can be represented as binary64 is

10.55499999999999971578290569595992565155029296875

And, if you round that number to two decimal places, you get 10.55.

Please reread https://sqlite.org/floatingpoint.html if you have not done so already.

(11) By jose isaias cabrera (jicman) on 2023-09-12 15:10:18 in reply to 9.1 [link] [source]

Expected result: 10.56

You may want to read this post. It's long, but worth it.

(12) By jmc (jmc123) on 2023-09-12 15:33:32 in reply to 7 [link] [source]

Sorry M. Hipp for this late reply

We don't use any 3rd-party tool

Our app is written in Tcl/Tk with SQLite interface

While this interface is bundled in relases of Tcl langage, we don't want to wait for new release (once a year) to benefit for improvement of each SQLite version.

So we found Mr Werner's (talented dev) site which provides a compilation service on line for various Tcl packages see : http://www.ch-werner.de/cgi-bin/luck.pl

So our SQLite library commes from there

We are trying to get in touch with Mr Werner

Thanks

(13) By jmc (jmc123) on 2023-09-12 15:51:56 in reply to 6 [link] [source]

Sorry M. Brasfield, I didn't saw your post at first

On my PC : SELECT round(146.36,2) - 146.36

 0.0

Thanks

(14) By jmc (jmc123) on 2023-09-12 16:07:58 in reply to 6 [link] [source]

AND (repeating myself, sorry) :

SELECT round(146.36,2)

146.35999999999999

SELECT round(146.36,3)

146.35999999999999

SELECT round(146.36,1)

146.4

SELECT round(146.36,0)

146.0

Thanks

(15) By Richard Hipp (drh) on 2023-09-12 16:15:20 in reply to 14 [link] [source]

We cannot reproduce your problem. You can repeat yourself all you want, but that will not help us to reproduce your problem. If we cannot reproduce the problem, there is no hope of getting it fixed.

You say you are using TCL. Please show us a short TCL script that will reproduce the problem, then.

Your problem is difficult to reproduce. Hence, it is on you to be very precise in your demonstration of the problem. Throwing some queries and answers on the screen is not sufficient. Show us exactly what you did to submit those queries and get the result.

(16) By jose isaias cabrera (jicman) on 2023-09-12 17:13:35 in reply to 14 [link] [source]

Will you copy the command prompt that starts your CLI? I.e.

12:00:46.31>sqlite3
-- Loading resources from C:\Users\e608313/.sqliterc
SQLite version 3.44.0 2023-09-05 15:03:23
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite>

(17.1) Originally by jmc (jmc123) with edits by Richard Hipp (drh) on 2023-09-12 17:56:48 from 17.0 in reply to 15 [link] [source]

Below is short demo of ou pb :


package require sqlite3
sqlite3 db1 :memory:
db1 eval "CREATE TABLE T1 ( A1 REAL )"
db1 eval "INSERT INTO T1 ( A1)
          VALUES (146.36)"
set res [db1 eval "SELECT round(A1,2)
                   FROM T1"]
if {$res != 146.36} {
  tk_messageBox -message "result : $res"
}
exit

Thanks

(18) By jmc (jmc123) on 2023-09-12 18:04:45 in reply to 17.1 [link] [source]

Forgot to mention that on my PC tk_messageBox fires and displays

"result : 146.35999999999999"

Thanks

(19) By jose isaias cabrera (jicman) on 2023-09-12 18:06:55 in reply to 17.1 [link] [source]

Add one more db1 eval with this string,

"SELECT sqlite_version(),sqlite_source_id();"

and print the output to your messageBox and tell us what it gives you.

(20) By jmc (jmc123) on 2023-09-12 18:11:14 in reply to 16 [link] [source]

Sorry for this late reply

I have no CLI installed on my PC, but if important I can download and install it

If you want the result of SELECT sqlite_source_id(), here it is :

2023-08-24 12:36:590b798b3f4b81a7bb4233c58294edd0f1156f36b6ecf5ab8e83631d468778c

(21) By Larry Brasfield (larrybr) on 2023-09-12 18:11:25 in reply to 17.1 [link] [source]

With the currently released SQLite3 and its Tcl adapter, that little program produces: 146.36 , without any message box.

What do you get with: db1 eval { select sqlite_version() } , (within the lifetime of the object known as "db1")?

(22) By jmc (jmc123) on 2023-09-12 18:21:06 in reply to 19 [link] [source]

I did this in posts #20 in this thread

our both posts reached this forum at same time I guess

Thanks

(23) By jmc (jmc123) on 2023-09-12 18:40:28 in reply to 21 [link] [source]

In the previous script, I added the following lines

set version [db1 eval "SELECT sqlite_version()"] set sourceId [db1 eval "SELECT sqlite_source_id()"]

tk_messageBox -message "$version n $sourceId"

The first line of message is :

3.43.0

However I can't copy and paste the value of $souceID from the tk_messageBox

So I copied it from a widget acting as a console in the app where the pb apeared at first, here it is :

2023-08-24 12:36:59 0f80b798b3f4b81a7bb4233c58294edd0f1156f36b6ecf5ab8e83631d468778c

(there is only one version of Tcl + SQlite on this PC)

(24) By jmc (jmc123) on 2023-09-12 19:00:58 in reply to 21 [link] [source]

From the replies of everybody, especialy from M. Hipp, and you, that nobody can reproduce the pb at all, it is easy to guess that even coming from the same source code, the executable is not exactly the same (see my post #12 in reply to M. Hipp)

If somebody is interresed in the result of our quest, let me know

So thank you for your replies and don't waste your time

Thanks again

(25) By jose isaias cabrera (jicman) on 2023-09-12 19:10:42 in reply to 24 [link] [source]

If somebody is interresed in the result of our quest, let me know

If would be beneficial if you place what you find out on this post. There may be others with the same problem and can find the solution when you post it.

(26) By jmc (jmc123) on 2023-09-13 11:41:19 in reply to 25 [link] [source]

The end of this story can be read in :

https://www.androwish.org/home/tktview/193726689b

(27) By jose isaias cabrera (jicman) on 2023-09-13 13:14:00 in reply to 26 [link] [source]

Thanks for providing the end of the story.

(28.1) By Simon Slavin (slavin) on 2023-09-14 13:43:16 edited from 28.0 in reply to 4 [link] [source]

Deleted

(29) By chwchw on 2023-09-13 20:09:07 in reply to 27 [link] [source]

Hmm, I'm still pretty unsure. I bet we need Episode 2 of it to be convinced, that toolchain mixing ain't no good idea. Had jmc used the 32 bit version, things were even more blurred, since my Win32 builds are without the shinyness of MMX/SSE/AVX/+++ but support even the good ole i486 dinosaurs. Which certainly the highly optimized MSVC tools learned to forget since a decade.

(30.1) Originally by jmc (jmc123) with edits by Dan Kennedy (dan) on 2023-09-14 11:28:29 from 30.0 in reply to 29 [link] [source]

While waiting for progress toward Episode 2, and just for curious people as I'm the only one to experience this, below is a new script in Tcl exhibiting the pb on my PC (sorry for poor formating). This scrip produces 2 text files : msg_round1.txt and msg_round2.txt

package require sqlite3

sqlite3 db1 :memory:

set version  [db1 eval "SELECT sqlite_version()"]
set sourceId [db1 eval "SELECT sqlite_source_id()"]

db1 eval "CREATE TABLE T1 ( A1 REAL )"
        
db1 eval "INSERT INTO T1 ( A1 )
          VALUES (1.125 ),
                 (1.125 )"

set res [db1 eval "SELECT round(total(round(A1,2)),2)
                   FROM T1"]

if {$res != 2.26} {
    
    set msgRound1 [open msg_round1.txt w]
    puts $msgRound1 "version : $version \nsourceId : $sourceId \nresult : $res"
 
    close $msgRound1
}

db1 eval "SELECT round(1.12515,0) AS A, round(1.12515,1) AS B, round(1.12515,2) AS C, round(1.12515,3) AS D, round(1.12515,4) AS E" {}

set msgRound2 [open msg_round2.txt w]
 
puts $msgRound2 "A = $A \nB = $B \nC = $C \nD = $D \nE = $E"
 
close $msgRound2

On my PC the content of the file msg_round1.txt is :

version : 3.43.0 
sourceId : {2023-08-24 12:36:59 0f80b798b3f4b81a7bb4233c58294edd0f1156f36b6ecf5ab8e83631d468778c} 

result : 2.2600000000000002

And the content of file msg_round2.txt is :

A = 1.0 

B = 1.1 

C = 1.1300000000000001 

D = 1.125 

E = 1.1252

(31) By Simon Slavin (slavin) on 2023-09-14 13:43:52 in reply to 4 [link] [source]

If you're asking for 146.3599, why is it saying 145.3599 in the column headers ?

From SQLite version 3.39.5 2022-10-14 20:58:05 I get

 sqlite> .mode box
sqlite> SELECT round(146.3599,1), round(146.3599,2);
┌───────────────────┬───────────────────┐
│ round(146.3599,1) │ round(146.3599,2) │
├───────────────────┼───────────────────┤
│ 146.4             │ 146.36            │
└───────────────────┴───────────────────┘

(32) By jmc (jmc123) on 2023-09-22 14:39:21 in reply to 30.1 [link] [source]

Below are new variations around my problem :
(the Tcl script is after the recap)

Recap :

1) Tcl + SQLite extension (version 3.40.0) both compiled with MSVC 64

SELECT with version 3.40.0

                                    |      read field    |  round 2 applied   |  round 3 applied   |  round 4 applied   |     quote() applied       | format '%2.f' | format '%2.f' cast as real
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.42.0 | 146.3599           | 146.36             | 146.36             | 146.3599           | 146.3599                  | 146.36        | 146.36
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.43.0 | 146.35989999999998 | 146.36             | 146.36             | 146.3599           | 1.4635989999999998723e+02 | 146.36        | 146.36
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


2) Mixture of Tcl compiled with MSVC 64 bits and SQLite extension compiled with MinGW 64

a) SELECT with version 3.42.0

   -> same result as 1) :

                                    |      read field    |  round 2 applied   |  round 3 applied   |  round 4 applied   |     quote() applied       | format '%2.f' | format '%2.f' cast as real
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.42.0 | 146.3599           | 146.36             | 146.36             | 146.3599           | 146.3599                  | 146.36        | 146.36
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.43.0 | 146.35989999999998 | 146.36             | 146.36             | 146.3599           | 1.4635989999999998723e+02 | 146.36        | 146.36
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

b) SELECT with version 3.43.0

                                    |      read field    |  round 2 applied   |  round 3 applied   |  round 4 applied   |     quote() applied       | format '%2.f' | format '%2.f' cast as real
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.42.0 | 146.3599           | 146.35999999999999 | 146.35999999999999 | 146.35989999999998 | 1.463599e+02              | 146.36        | 146.35999999999999
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.43.0 | 146.35989999999998 | 146.35999999999999 | 146.35999999999999 | 146.35989999999998 | 146.3599                  | 146.36        | 146.35999999999999
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Notice the slight difference on the last digit in version 3.43.0 between "read field" vs "round 2 applied" or vs "format '%2.f' cast as real"


3) Tcl + SQLite extension (version 3.43.1) both compiled with MinGW 64

SELECT with version 3.43.1

   -> same result as 1) and 2a) :

                                    |      read field    |  round 2 applied   |  round 3 applied   |  round 4 applied   |     quote() applied       | format '%2.f' | format '%2.f' cast as real
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.42.0 | 146.3599           | 146.36             | 146.36             | 146.3599           | 146.3599                  | 146.36        | 146.36
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
value 146.3599 inserted with 3.43.0 | 146.35989999999998 | 146.36             | 146.36             | 146.3599           | 1.4635989999999998723e+02 | 146.36        | 146.36
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Tcl script :

package require -exact sqlite3 3.42.0

sqlite3 db1 demoDB

db1 eval "DROP TABLE IF EXISTS T1;
          CREATE TABLE T1 ( Version TEXT, Value REAL );
          INSERT INTO T1 ( Version, Value ) VALUES (sqlite_version(), 146.3599)"

db1 close


package require -exact sqlite3 3.43.0

sqlite3 db1 demoDB

db1 eval "INSERT INTO T1 ( Version, Value ) VALUES (sqlite_version(), 146.3599)"

db1 close


package require -exact sqlite3 3.42.0

sqlite3 db1 demoDB

db1 eval "SELECT Version, Value, round(Value,2) AS 'round2', round(Value,3) AS 'round3', round(Value,4) AS 'round4',
                 quote(Value) AS 'quoteValue', format('%.2f', Value) AS 'formatValue', CAST (format('%.2f', Value) AS 'REAL') AS 'castFormat'
          FROM T1" {
            puts "$Version $Value $round2 $round3 $round4 $quoteValue $formatValue $castFormat" 
          }

db1 close


package require -exact sqlite3 3.43.0

sqlite3 db1 demoDB

db1 eval "SELECT Version, Value, round(Value,2) AS 'round2', round(Value,3) AS 'round3', round(Value,4) AS 'round4',
                 quote(Value) AS 'quoteValue', format('%.2f', Value) AS 'formatValue', CAST (format('%.2f', Value) AS 'REAL') AS 'castFormat'
          FROM T1" {
            puts "$Version $Value $round2 $round3 $round4 $quoteValue $formatValue $castFormat" 
          }

db1 close

(33) By Richard Hipp (drh) on 2023-09-22 14:49:39 in reply to 32 [link] [source]

Have you tried your experiments using the latest trunk check-in of SQLite?

(34) By jmc (jmc123) on 2023-09-27 08:34:48 in reply to 33 [link] [source]

Sorry Mr Hipp for this late reply

I can't compile myself any C source code as, unfortunately, I have not the necessary skills to do so (nor a C compiler)

However, I have recently obtained the latest release (3.43.1) of SQLite compiled whith latest Visual Studio from the person distributing the Tcl langage for Windows we use (both compiled with MSVC but maybe not exactly same version)

All our tests this morning with this 3.43.1 compiled with MSVC are OK and our previous problem has disapeared.

So it seems the source of our pb was wixing Tcl langage compiled with MSVC and SQLite extension for Tcl compiled with MingW

Thank you again