Re: numeric calculation bug as of 16.2-2

From: Huw Rogers <djnz00(at)gmail(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: David Rowley <dgrowleyml(at)gmail(dot)com>, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: numeric calculation bug as of 16.2-2
Date: 2024-05-14 05:04:09
Message-ID: CACu6R2qXrCkNtdW8B9yzC=+gxo3hy5jatf1qaaQaLNaktAgA=Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Thanks for the reply; as you found, actually I was testing with (2^127-1),
not 2^127, and apparently that makes the difference. (((2^127)-1)/(2^63))

The reason I think it's a bug is that I would not expect an off-by-one
result. I would expect some fractional error of much less than one. It's
also suspicious that this is triggered by an all-binary-ones value.

For now I'm just using a WITH INOUT cast for this, which works fine,
although it would be easier for my purposes (adding int128 and uint128
types via an extension) to expose numericvar_to_int128() and
int128_to_numericvar via numeric.h so that extensions could use them.

This would be the corrected test:

=# select ((2^127::numeric - 1::numeric)/(2^63::numeric))*(2^63::numeric) =
(2^127::numeric - 1::numeric);
?column?
----------
f
(1 row)

On Tue, May 14, 2024 at 1:12 PM Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> wrote:

> David Rowley <dgrowleyml(at)gmail(dot)com> writes:
> > On Tue, 14 May 2024 at 14:53, Huw Rogers <djnz00(at)gmail(dot)com> wrote:
> >> test=# select ('170141183460469231731687303715884105727'::numeric /
> '9223372036854775808'::numeric) * '9223372036854775808'::numeric;
> >> ?column?
> >> -----------------------------------------
> >> 170141183460469231731687303715884105728
>
> > I don't have enough experience in NUMERIC to tell if this is a bug or
> > not.
>
> It is not. If you think that using numeric (or any other
> general-purpose arithmetic code) means you'll always get exact answers
> for every calculation, I have a bridge in Brooklyn I'd like to sell
> you.
>
> The specific problem with the example you give is that you're using
> fractional-power-of-2 numbers and expecting them to be exactly
> representable in numeric's base-10 arithmetic. That's not happening.
>
> Amusingly, type float8 (which is binary at bottom) can represent
> such numbers exactly, so that this works:
>
> =# select ((2^127)/(2^63))*(2^63) = (2^127);
> ?column?
> ----------
> t
>
> (Use pg_typeof to verify that the subexpressions are type float8.)
>
> Nonetheless, float8 has a well-deserved reputation for being imprecise
> with the decimal fractions that people commonly work with. That's
> just the opposite side of the same coin: conversion between the two
> bases is inexact, unless you are willing to work with an unlimited
> number of fractional digits, which in practice nobody is.
>
> BTW, just as a point of order, I cannot reproduce your complaint:
>
> =# select ((2^127::numeric)/(2^63::numeric))*(2^63::numeric) =
> (2^127::numeric);
> ?column?
> ----------
> t
> (1 row)
>
> =# select (2^127::numeric), (2^63::numeric);
> ?column? | ?column?
> -----------------------------------------+---------------------
> 170141183460469231731687303715884105728 | 9223372036854775808
> (1 row)
>
> =# select
> (170141183460469231731687303715884105728/9223372036854775808)*9223372036854775808
> = 170141183460469231731687303715884105728;
> ?column?
> ----------
> t
> (1 row)
>
> I don't know where you got '170141183460469231731687303715884105727'
> from, but that seems off-by-one. This doesn't invalidate my larger
> point though.
>
> regards, tom lane
>

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message PG Bug reporting form 2024-05-14 05:19:19 BUG #18462: Wrong SELinux types of the binary files
Previous Message Tom Lane 2024-05-14 04:12:15 Re: numeric calculation bug as of 16.2-2