Thread

  1. BUG in postgres mathematic

    Max Vaschenko <max@nino.ru> — 2001-01-25T10:34:02Z

    Postgres-7.0.3-2
    RedHat-6.2
    
    SELECT int8(5*27.81*100);
    13904
    
    SELECT int4(5*27.81*100);
    13905
    
    SELECT int8(27.81*100*5);
    13905
    
    -- 
    С уважением, Ващенко Максим,
    Нижегородские информационные сети
    (8312) 30-19-05, 34-00-02, 30-09-73
    
    With best regards, Max Vaschenko,
    Nizhny Novgorod Information Networks.
    
    
  2. Re: BUG in postgres mathematic

    Robert B. Easter <reaster@comptechnews.com> — 2001-01-25T12:29:00Z

    This problem is not specific to Postgres. If you play around with a little C 
    program like:
    
    #include <stdio.h>
     
    int main(int argc, char * argv[])
    {
            float f = 27.81;
            int i = 5;
            int l = 100;
     
            int ii = i*f*l;
            long ll = l*f*i;
            float ff = i*f*l;
     
            printf("%i\n", ii);
            printf("%li\n", ll);
            printf("%.5f\n", ff);
            printf("%i\n", (int) ff);
    }                
    
    It prints:
    
    13904
    13904
    13905.00000
    13905   
    
    There is probably a good explanation for this.  gcc 2.95 and egcs 2.91.66 do 
    this.  Maybe a rounding problem.
    
    On Thursday 25 January 2001 05:34, Max Vaschenko wrote:
    > Postgres-7.0.3-2
    > RedHat-6.2
    >
    > SELECT int8(5*27.81*100);
    > 13904
    >
    > SELECT int4(5*27.81*100);
    > 13905
    >
    > SELECT int8(27.81*100*5);
    > 13905
    
    -- 
    -------- Robert B. Easter  reaster@comptechnews.com ---------
    -- CompTechNews Message Board http://www.comptechnews.com/ --
    -- CompTechServ Tech Services http://www.comptechserv.com/ --
    ---------- http://www.comptechnews.com/~reaster/ ------------
    
    
  3. Re: BUG in postgres mathematic

    Tom Lane <tgl@sss.pgh.pa.us> — 2001-01-26T03:52:30Z

    "Robert B. Easter" <reaster@comptechnews.com> writes:
    > This problem is not specific to Postgres.
    
    The fact that 5*27.81*100 != 27.81*100*5 is certainly a garden-variety
    floating-point roundoff error.  However, I think Max has a fair
    complaint here: it seems float-to-int8 conversion is truncating, not
    rounding like the other conversions to integer do.
    
    regression=# select 4.7::float8::int4;
     ?column?
    ----------
            5
    (1 row)
    
    regression=# select 4.7::float8::int8;
     ?column?
    ----------
            4
    (1 row)
    
    Seems to me this is a bug we should fix.
    
    			regards, tom lane
    
    
  4. Re: BUG in postgres mathematic

    Robert B. Easter <reaster@comptechnews.com> — 2001-01-26T05:49:46Z

    On Thursday 25 January 2001 22:52, Tom Lane wrote:
    > "Robert B. Easter" <reaster@comptechnews.com> writes:
    > > This problem is not specific to Postgres.
    >
    > The fact that 5*27.81*100 != 27.81*100*5 is certainly a garden-variety
    > floating-point roundoff error.  However, I think Max has a fair
    > complaint here: it seems float-to-int8 conversion is truncating, not
    > rounding like the other conversions to integer do.
    >
    > regression=# select 4.7::float8::int4;
    >  ?column?
    > ----------
    >         5
    > (1 row)
    >
    > regression=# select 4.7::float8::int8;
    >  ?column?
    > ----------
    >         4
    > (1 row)
    >
    > Seems to me this is a bug we should fix.
    >
    > 			regards, tom lane
    
    Yeah, I agree. It isn't right that it truncates and that is something C does 
    appearently.  The fix is to pass the float through a rounding something like 
    (long)(f + 0.5) or else C just truncates it off.  This must already be 
    happening for the int4 conversion or C would do the same thing to it.  I 
    didn't look at the Postgres sources yet, but it is probably one of those very 
    easy things to fix. :)
    
    
    -- 
    -------- Robert B. Easter  reaster@comptechnews.com ---------
    -- CompTechNews Message Board http://www.comptechnews.com/ --
    -- CompTechServ Tech Services http://www.comptechserv.com/ --
    ---------- http://www.comptechnews.com/~reaster/ ------------
    
    
  5. Re: BUG in postgres mathematic

    Tom Lane <tgl@sss.pgh.pa.us> — 2001-01-26T23:07:05Z

    >> The fact that 5*27.81*100 != 27.81*100*5 is certainly a garden-variety
    >> floating-point roundoff error.  However, I think Max has a fair
    >> complaint here: it seems float-to-int8 conversion is truncating, not
    >> rounding like the other conversions to integer do.
    
    I have changed float8-to-int8 to start with an rint() call, the same as
    float8-to-int4 and float8-to-int2.  This should give the same roundoff
    behavior as the other cases, including round-to-nearest-even if your
    hardware supports IEEE-compliant float math.
    
    Curiously, this change exposed what I take to be a platform dependency
    in the int8 regress test.  It was computing
    int8(float8(4567890123456789::int8)) and expecting to get back exactly
    4567890123456789.  However, that value is 53 bits long and so there is
    no margin for error in a standard IEEE float8 value.  I find that at
    least on HP hardware, rint() treats the value as inexact and rounds to
    nearest even:
    
    regression=# select round(4567890123456788::float8) - 4567890123456780::float8;
     ?column?
    ----------
            8
    (1 row)
    
    regression=# select round(4567890123456789::float8) - 4567890123456780::float8;
     ?column?
    ----------
            8
    (1 row)
    
    regression=# select round(4567890123456790::float8) - 4567890123456780::float8;
     ?column?
    ----------
           10
    (1 row)
    
    regression=#
    
    Whether this is a bug in rint or spec-compliant behavior is unclear, but
    I'll bet HP's hardware is not the only platform that behaves this way.
    Since I'm not eager to try to develop a new set of platform-specific
    int8 expected files at this late hour, I just diked out that test
    instead...
    
    			regards, tom lane
    
    
  6. Re: BUG in postgres mathematic

    Robert B. Easter <reaster@comptechnews.com> — 2001-01-27T00:31:35Z

    On Friday 26 January 2001 18:07, Tom Lane wrote:
    > Curiously, this change exposed what I take to be a platform dependency
    > in the int8 regress test.  It was computing
    > int8(float8(4567890123456789::int8)) and expecting to get back exactly
    > 4567890123456789.  However, that value is 53 bits long and so there is
    > no margin for error in a standard IEEE float8 value.  I find that at
    > least on HP hardware, rint() treats the value as inexact and rounds to
    > nearest even:
    >
    > regression=# select round(4567890123456788::float8) -
    > 4567890123456780::float8; ?column?
    > ----------
    >         8
    > (1 row)
    >
    > regression=# select round(4567890123456789::float8) -
    > 4567890123456780::float8; ?column?
    > ----------
    >         8
    > (1 row)
    >
    > regression=# select round(4567890123456790::float8) -
    > 4567890123456780::float8; ?column?
    > ----------
    >        10
    > (1 row)
    >
    > regression=#
    >
    > Whether this is a bug in rint or spec-compliant behavior is unclear, but
    > I'll bet HP's hardware is not the only platform that behaves this way.
    > Since I'm not eager to try to develop a new set of platform-specific
    > int8 expected files at this late hour, I just diked out that test
    > instead...
    
    Here is what I get on Linux (PIII):
    
    reaster=# select round(4567890123456788::float8) - 4567890123456780::float8;
     ?column?
    ----------
            8
    (1 row)
     
    reaster=# select round(4567890123456789::float8) - 4567890123456780::float8;
     ?column?
    ----------
            9
    (1 row)
     
    reaster=# select round(4567890123456790::float8) - 4567890123456780::float8;
     ?column?
    ----------
           10
    (1 row)  
    
    I'm not sure what the problem is either.  The PIII has an 80-bit FPU but not 
    sure that matters.  When there is no exponent, maybe only 52 bits are really 
    in the mantissa.  If you try rounding numbers <= 4503599627370495 (2^52 - 1), 
    maybe you'll get expected results.  The hidden bit is 0.  Could be that round 
    or rint (whatever it is) always makes the hidden bit 1 when I think it should 
    only be 1 when the exponent is nonzero.  I'm no float expert! :)  Feel free 
    to correct me.
    
    
    -- 
    -------- Robert B. Easter  reaster@comptechnews.com ---------
    -- CompTechNews Message Board http://www.comptechnews.com/ --
    -- CompTechServ Tech Services http://www.comptechserv.com/ --
    ---------- http://www.comptechnews.com/~reaster/ ------------