The 85/0.0085 mistery ?
Hi,
Well, I discovered a strange behavior (ie 85/0.0085 <> 10000 )
Is my SQL wrong or is it postgres ?
We are running 7.02 (but also 6.x) on a alpha (alphaev6) box.
Thanks in advance.
jc
Here is a snapshot
jctest=> create table eigthyfive ( cs float4, csbytenthousand float4,
csbyhundred float);
CREATE
jctest=> insert into eigthyfive VALUES (88,0.0088,0.88);
INSERT 7973003 1
jctest=> insert into eigthyfive VALUES (86,0.0086,0.86);
INSERT 7973004 1
jctest=> insert into eigthyfive VALUES (85,0.0085,0.85);
INSERT 7973005 1
jctest=> insert into eigthyfive VALUES (84,0.0084,0.84);
INSERT 7973006 1
jctest=> select * from eigthyfive ;
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
88 | 0.0088 | 0.88
86 | 0.0086 | 0.86
85 | 0.0085 | 0.85
84 | 0.0084 | 0.84
(4 rows)
jctest=> select * from eigthyfive where (cs/csbytenthousand=10000);
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
88 | 0.0088 | 0.88
86 | 0.0086 | 0.86
84 | 0.0084 | 0.84
(3 rows)
*** oh oh 85 disappeared ! ***
BUT
jctest=> select (85/0.0085=10000);
?column?
----------
t
(1 row)
jctest=> select * from eigthyfive where (cs/csbyhundred=100);
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
88 | 0.0088 | 0.88
86 | 0.0086 | 0.86
85 | 0.0085 | 0.85
84 | 0.0084 | 0.84
(4 rows)
** 85 is back **
jctest=> insert into eigthyfive VALUES (85,0.00085);
INSERT 7973007 1
jctest=> select * from eigthyfive where (cs/csbytenthousand=100000);
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
85 | 0.00085 |
(1 row)
Nothing is wrong, that's just how computers work. Fractional numbers are
stored in a variety of formats on different platforms. Most support the
IEEE formats, but some use their own formats. In all cases, that I'm aware
of, the numbers are stored as a mantissa and exponent. The numbers are
"base 2", so certain base 10 numbers don't have an exact representation in
base 2, no matter how many bits are used in the mantissa. Other base 10
numbers have problems with the "short" mantissa formats, but are represented
exactly with the "long" mantissa formats.
In general, it's recommended you don't check for exact equivalence when
doing calculations on real numbers and instead check for "almost exactness."
In other words, depending on the format used on your machine, 85/0.0085 may
be equal to 1000.000000000000001.
Of course, this may all be wrong, but that's my understanding. I think they
mention this in the docs for the regression tests. Check them out!
Fred Reimer
Eclipsys Corporation
Show quoted text
-----Original Message-----
From: pgsql-hackers-owner@hub.org
[mailto:pgsql-hackers-owner@hub.org]On
Behalf Of Jean-Christophe Pazzaglia
Sent: Friday, October 06, 2000 8:28 AM
To: PostgreSQL-development
Subject: [HACKERS] The 85/0.0085 mistery ?Hi,
Well, I discovered a strange behavior (ie 85/0.0085 <> 10000 )
Is my SQL wrong or is it postgres ?
We are running 7.02 (but also 6.x) on a alpha (alphaev6) box.Thanks in advance.
jc
Here is a snapshot
jctest=> create table eigthyfive ( cs float4, csbytenthousand float4,
csbyhundred float);
CREATEjctest=> insert into eigthyfive VALUES (88,0.0088,0.88);
INSERT 7973003 1
jctest=> insert into eigthyfive VALUES (86,0.0086,0.86);
INSERT 7973004 1
jctest=> insert into eigthyfive VALUES (85,0.0085,0.85);
INSERT 7973005 1
jctest=> insert into eigthyfive VALUES (84,0.0084,0.84);
INSERT 7973006 1jctest=> select * from eigthyfive ;
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
88 | 0.0088 | 0.88
86 | 0.0086 | 0.86
85 | 0.0085 | 0.85
84 | 0.0084 | 0.84
(4 rows)jctest=> select * from eigthyfive where (cs/csbytenthousand=10000);
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
88 | 0.0088 | 0.88
86 | 0.0086 | 0.86
84 | 0.0084 | 0.84
(3 rows)*** oh oh 85 disappeared ! ***
BUT
jctest=> select (85/0.0085=10000);
?column?
----------
t
(1 row)jctest=> select * from eigthyfive where (cs/csbyhundred=100);
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
88 | 0.0088 | 0.88
86 | 0.0086 | 0.86
85 | 0.0085 | 0.85
84 | 0.0084 | 0.84
(4 rows)** 85 is back **
jctest=> insert into eigthyfive VALUES (85,0.00085);
INSERT 7973007 1
jctest=> select * from eigthyfive where (cs/csbytenthousand=100000);
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
85 | 0.00085 |
(1 row)
"Frederick W. Reimer" wrote:
Nothing is wrong, that's just how computers work. Fractional numbers are
stored in a variety of formats on different platforms. Most support the
IEEE formats, but some use their own formats. In all cases, that I'm aware
of, the numbers are stored as a mantissa and exponent. The numbers are
"base 2", so certain base 10 numbers don't have an exact representation in
base 2, no matter how many bits are used in the mantissa. Other base 10
numbers have problems with the "short" mantissa formats, but are represented
exactly with the "long" mantissa formats.
thank you for the lesson,
I probably have done too much database this time :o
what I was really affraid was the BUT clause ...
jctest=> select * from eigthyfive where (cs/csbytenthousand=10000);
cs | csbytenthousand | csbyhundred
----+-----------------+-------------
88 | 0.0088 | 0.88
86 | 0.0086 | 0.86
84 | 0.0084 | 0.84
(3 rows)*** oh oh 85 disappeared ! ***
BUT
jctest=> select (85/0.0085=10000);
?column?
----------
t
(1 row)
... It seems that this is due to the single precision
(float4) instead of double precision (float)
(and even with a test done in base 3 :P)
BTW there is no round(float4) function
thanks
jc
Tom Lane wrote:
"Frederick W. Reimer" <fwr@ga.prestige.net> writes:
In general, it's recommended you don't check for exact equivalence when
doing calculations on real numbers and instead check for "almost exactness."
perhaps "where trunc(85/0.0085) = 10000" works better.
Or use datatype NUMERIC, which behaves in a more intuitive way (at least
for people who are accustomed to thinking in decimal). But yes, exact
equality checks on float values are usually foolish.
But ...
hannu=# create table ntest(n numeric(3), n1 numeric(6,4));
CREATE
hannu=# insert into ntest values(80, 80/10000);
INSERT 311338 1
hannu=# insert into ntest values(81, 81/10000);
INSERT 311339 1
hannu=# select count(*) from ntest where n/n1 = 10000;
ERROR: division by zero on numeric
hannu=# select * from ntest;
n | n1
----+--------
80 | 0.0000
81 | 0.0000
eek !
I understand why this is so, but should it be ?
Can't we assume that 80/10000 is numeric and back-propagate that
knowledge to constituents so that 80 and 10000 are also considered
numetics.
Or even better assume that 80/10000 is a rational number ;)
-------------------
Hannu
Hannu Krosing wrote:
Tom Lane wrote:
"Frederick W. Reimer" <fwr@ga.prestige.net> writes:
In general, it's recommended you don't check for exact equivalence when
doing calculations on real numbers and instead check for "almost exactness."perhaps "where trunc(85/0.0085) = 10000" works better.
ok I tested it and it does not work ;(
hannu=# select trunc(85.0::float4/0.0085::float4) = '10000';
ERROR: Function 'trunc(float4)' does not exist
Unable to identify a function that satisfies the given argument types
You may need to add explicit typecasts
hannu=# select trunc(float8(85.0::float4/0.0085::float4));
trunc
-------
9999
(1 row)
But this does work
hannu=# select text(85.0::float4/0.0085::float4) = '10000';
?column?
----------
t
(1 row)
As does this
hannu=# select round(float8(85.0::float4/0.0085::float4));
round
-------
10000
(1 row)
--------------
Hannu
"Frederick W. Reimer" <fwr@ga.prestige.net> writes:
In general, it's recommended you don't check for exact equivalence when
doing calculations on real numbers and instead check for "almost exactness."
Or use datatype NUMERIC, which behaves in a more intuitive way (at least
for people who are accustomed to thinking in decimal). But yes, exact
equality checks on float values are usually foolish.
regards, tom lane