On 2015/11/05 4:55 PM, Richard Hipp wrote:
> On 11/5/15, Zsb?n Ambrus <ambrus at math.bme.hu> wrote:
>> Dear SQLite,
>>
>> It seems that equality of numeric values isn't transitive, when both
>> integers and reals are involved.  Here's an example output from the
>> shell, which shows that the numeric value in the 'c' row is equal to
>> both the value in the 'b' and the 'd' rows, but the value in the 'b'
>> row isn't equal to the value in the 'd' row.  Neither null values nor
>> collations seem to be involved here.
>>
>> SQLite version 3.9.2 2015-11-02 18:31:45
>> Enter ".help" for usage hints.
>> Connected to a transient in-memory database.
>> Use ".open FILENAME" to reopen on a persistent database.
>> sqlite> create table tb(n, v);
>> sqlite> insert into tb(n, v) values ('b', 1<<58), ('c', (1<<58) +
>> 1e-7), ('d', (1<<58) + 1);
>> sqlite> select n, v, typeof(v) from tb;
>> b|288230376151711744|integer
>> c|2.88230376151712e+17|real
>> d|288230376151711745|integer
>> sqlite> select l.n, r.n, l.v = r.v from tb as l, tb as r;
>> b|b|1
>> b|c|1
>> b|d|0
>> c|b|1
>> c|c|1
>> c|d|1
>> d|b|0
>> d|c|1
>> d|d|1
>> sqlite> .quit
> The following C program gives the same answer (using gcc 4.8.4 on ubuntu):
>
> #include <stdio.h>
> typedef long long int i64;
> int main(int argc, char **argv){
>    i64 b = 1LL << 58;
>    double c = (1LL << 58) + 1e-7;
>    i64 d = (1LL << 58) + 1;
>    printf("b==b: %d\n", b==b);
>    printf("b==c: %d\n", b==c);
>    printf("b==d: %d\n", b==d);
>    printf("c==b: %d\n", c==b);
>    printf("c==c: %d\n", c==c);
>    printf("c==d: %d\n", c==d);
>    printf("d==b: %d\n", d==b);
>    printf("d==c: %d\n", d==c);
>    printf("d==d: %d\n", d==d);
>    return 0;
> }
>
>
>> Can this cause problems with indexes,
>> sorting or grouping by?
>>
> You should not compare floating-point numbers for equality.
> Floating-point numbers are, by definition, approximations.  When you
> compare floating-point numbers, therefore, you get an approximate
> answer.
>

fwiw - I don't get the same result, here is the same script running in 
Win32-SQLitespeed-via-SQLite-3.9.1-DLL (the standard pre-compiled one 
from sqlite.org) on an in-memory Database, This one seems to magically 
get it right:

   -- 2015-11-05 16:41:54.666  |  [Info]       Script Initialized, 
Started executing...
   -- 
================================================================================================

create table tb(n, v);

insert into tb(n, v) values ('b', 1<<58), ('c', (1<<58) + 1e-7), ('d', 
(1<<58) + 1);

select n, v, typeof(v) from tb;

   --   n   | v                      | typeof(v)
   -- ----- | ---------------------- | ---------
   --   b   | 288230376151711744     | integer
   --   c   | 2.88230376151712e+17   | real
   --   d   | 288230376151711745     | integer


select l.n, r.n, l.v = r.v from tb as l, tb as r;

   --   n   |   n   | l.v = r.v
   -- ----- | ----- | ---------
   --   b   |   b   |     1
   --   b   |   c   |     1
   --   b   |   d   |     0
   --   c   |   b   |     1
   --   c   |   c   |     1
   --   c   |   d   |     0
   --   d   |   b   |     0
   --   d   |   c   |     0
   --   d   |   d   |     1

   -- 2015-11-05 16:41:54.675  |  [Success]    Script Success.


And to answer the OP's other question - This doesn't matter, a Primary 
key using FLOAT values is rather risky, but any float that isn't 
represented exactly the same as another will have a different bit 
pattern. Mixing floats and ints in a PK however, might be disastrous.


Reply via email to