Am I missing something here?

agelis=# select B'1'::int;
  int4
------
     1
(1 row)

agelis=# select 1::bit;
  bit
-----
  0
(1 row)

agelis=# select B'1'=1;
  ?column?
----------
  f
(1 row)

Last I checked, binary 1 and integer 1 were equal.  Is this a bug, or is there
a reason for this that I need educated on?  Why does int 1 cast to binary 0?

This is Posgres 7.4.1.

-- 
Bill Moran
Potential Technologies
http://www.potentialtech.com


Wed, 03 Mar 2004 16:42:34 -0500
Bill Moran <wmoran@potentialtech.com>
Shouldn't B'1' = 1::bit be true?

On Wed, 3 Mar 2004, Bill Moran wrote:

> Am I missing something here?
>
> agelis=# select B'1'::int;
>   int4
> ------
>      1
> (1 row)
>
> agelis=# select 1::bit;
>   bit
> -----
>   0
> (1 row)
>
> agelis=# select B'1'=1;
>   ?column?
> ----------
>   f
> (1 row)
>
> Last I checked, binary 1 and integer 1 were equal.  Is this a bug, or is there
> a reason for this that I need educated on?  Why does int 1 cast to binary 0?

Hmm, on my 7.4 machine, I get an error saying that there's no = operator
for bit and integer.  If I cast the B'1' into an integer I get a true
result.

The reason for 1::bit being 0 is that int4 -> bit(n) casts cast to a 32
bit bit string.  IIRC, when bit strings are truncated for size in casts,
the spec says to take from the left.



Tue, 9 Mar 2004 15:34:36 -0800 (PST)
Stephan Szabo <sszabo@megazone.bigpanda.com>
Re: Shouldn't B'1' = 1::bit be true?
Bill Moran <wmoran@potentialtech.com> writes:
> Am I missing something here?

Hmm.  It seems like int-to-bit casting ought to be aware of the
bit-width one is casting to, and take that number of bits from
the right end of the integer.  This would make it be the inverse
of the other direction.  Right now it's only an inverse when you
cast to and from bit(32).  For shorter bitfield widths, we're
effectively inserting at the right end of the integer, but removing
bits from the left, which is not consistent.

regression=# select B'11000'::bit(5)::int;
 int4
------
   24
(1 row)

regression=# select 24::int::bit(32);
               bit
----------------------------------
 00000000000000000000000000011000
(1 row)

regression=# select 24::int::bit(32)::bit(5);
  bit
-------
 00000
(1 row)

regression=# select 24::int::bit(5);
  bit
-------
 00000
(1 row)

If we made int-to-bit-N take the rightmost N bits, then the last two
cases would yield different results, but that doesn't seem unreasonable
to me.  Or at least it's less unreasonable than bit(5)-to-int not being
the inverse of int-to-bit(5).

Comments?

			regards, tom lane

Tue, 09 Mar 2004 18:43:58 -0500
Tom Lane <tgl@sss.pgh.pa.us>
Re: Shouldn't B'1' = 1::bit be true? 
Stephan Szabo wrote:
> On Wed, 3 Mar 2004, Bill Moran wrote:
> 
> 
>>Am I missing something here?
>>
>>agelis=# select B'1'::int;
>>  int4
>>------
>>     1
>>(1 row)
>>
>>agelis=# select 1::bit;
>>  bit
>>-----
>>  0
>>(1 row)
>>
>>agelis=# select B'1'=1;
>>  ?column?
>>----------
>>  f
>>(1 row)
>>
>>Last I checked, binary 1 and integer 1 were equal.  Is this a bug, or is there
>>a reason for this that I need educated on?  Why does int 1 cast to binary 0?
> 
> Hmm, on my 7.4 machine, I get an error saying that there's no = operator
> for bit and integer.  If I cast the B'1' into an integer I get a true
> result.
> 
> The reason for 1::bit being 0 is that int4 -> bit(n) casts cast to a 32
> bit bit string.  IIRC, when bit strings are truncated for size in casts,
> the spec says to take from the left.

Yeah.  I made some changes to the casting config, so that int to bit is
cast automatically, instead of requiring an explicit cast.  It made the
code I was converting easier to manage.

I dont' know why my original email took so long to hit the list, but I did
find out the same thing you just described.  In the end I ended up converting
all the bit functions to int, so that I don't have to deal with the casting
pecularities, which just seemed like the easiest solution at the time.

-- 
Bill Moran
Potential Technologies
http://www.potentialtech.com


Tue, 09 Mar 2004 19:31:06 -0500
Bill Moran <wmoran@potentialtech.com>
Re: Shouldn't B'1' = 1::bit be true?
<quote who="Tom Lane">
> Bill Moran <wmoran@potentialtech.com> writes:
>> Am I missing something here?
>
> Hmm.  It seems like int-to-bit casting ought to be aware of the
> bit-width one is casting to, and take that number of bits from
> the right end of the integer.  This would make it be the inverse
> of the other direction.  Right now it's only an inverse when you
> cast to and from bit(32).  For shorter bitfield widths, we're
> effectively inserting at the right end of the integer, but removing
> bits from the left, which is not consistent.
>
> regression=# select B'11000'::bit(5)::int;
>  int4
> ------
>    24
> (1 row)
>
> regression=# select 24::int::bit(32);
>                bit
> ----------------------------------
>  00000000000000000000000000011000
> (1 row)
>
> regression=# select 24::int::bit(32)::bit(5);
>   bit
> -------
>  00000
> (1 row)
>
> regression=# select 24::int::bit(5);
>   bit
> -------
>  00000
> (1 row)
>
> If we made int-to-bit-N take the rightmost N bits, then the last two
> cases would yield different results, but that doesn't seem unreasonable
> to me.  Or at least it's less unreasonable than bit(5)-to-int not being
> the inverse of int-to-bit(5).
>
> Comments?
>

Tom,

I would suggest looking at char to int to char conversions for correctness
examples.  This can be looked at as bit(8)::bit(32)::bit(8) operations.

To convert low bits ot high bits you pad 0 bits on the left.   To convert
from high to low you strip bits off the left hand side.  This allows
reasonable behavior.

Coverting from low precision to high precision and back to low precision
should be lossless for bits.   High to low to high should be lossy for
bits because you lost bits in the smaller container.

So the conversion should be symmetric for values that fit in the bitspace.
 Even the MS calculator does this. 65534::bit(8)::int should yield 254
just as 254::int::bit(8) should be 254 and 254::int::bit(32)::bit(8)::int
should yield 254.

I would say the current way of handling bit conversions is broken.  I for
one would like to see the bitwise behavior be more correct.   It's almost
as if the bit(32)::bit(8) operation is thinking of string truncation.  Is
this endian related?

Thomas


Wed, 10 Mar 2004 12:45:13 -0600 (CST)
"Thomas Swan" <tswan@idigx.com>
Re: [GENERAL] Shouldn't B'1' = 1::bit be true?
"Thomas Swan" <tswan@idigx.com> writes:
> To convert low bits ot high bits you pad 0 bits on the left.   To convert
> from high to low you strip bits off the left hand side.  This allows
> reasonable behavior.

Unfortunately, the SQL spec is perfectly clear that you pad or strip
zero bits on the *right* of the bit string.  We cannot change that.

It might have been better if we had defined int<->bit casts to treat
the first bit of the bit string as the LSB of the integer.  But we
didn't, and it's probably too big a change to consider.

			regards, tom lane

Wed, 10 Mar 2004 14:06:00 -0500
Tom Lane <tgl@sss.pgh.pa.us>
Re: [HACKERS] Shouldn't B'1' = 1::bit be true? 
<quote who="Tom Lane">
> "Thomas Swan" <tswan@idigx.com> writes:
>> To convert low bits ot high bits you pad 0 bits on the left.   To
>> convert
>> from high to low you strip bits off the left hand side.  This allows
>> reasonable behavior.
>
> Unfortunately, the SQL spec is perfectly clear that you pad or strip
> zero bits on the *right* of the bit string.  We cannot change that.
>

I was completely unaware of that fact. *must dig a deeper hole*

> It might have been better if we had defined int<->bit casts to treat
> the first bit of the bit string as the LSB of the integer.  But we
> didn't, and it's probably too big a change to consider.
>

It would be a big change at least in the 7.x series.  Maybe the change
could be tabled to an 8.x release.

Thomas


Wed, 10 Mar 2004 17:18:55 -0600 (CST)
"Thomas Swan" <tswan@idigx.com>
Re: [GENERAL] Shouldn't B'1' = 1::bit be true?