How to get rid of FutureWarning: hex/oct constants...
Bengt Richter
bokr at oz.net
Sun Mar 27 19:44:22 EST 2005
On Sun, 27 Mar 2005 12:48:46 +0200, =?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?= <martin at v.loewis.de> wrote:
>Bengt Richter wrote:
>> >>> hex(-2*0x40000000+0x40047a80)
>> __main__:1: FutureWarning: hex()/oct() of negative int will return a signed string in Python 2.4
>> and up
>> '0xc0047a80'
>>
>> That "signed string" is a unary minus expression using an absolute value forced by the inadequacy
>> of the literal representation syntax.
>> IOW, IMO '-' + hex_literal_of(abs(x)) is not a decent hex_literal_of(-x) !!
>
>This has been discussed over and over, but since you bring it up again:
It seems you have a different concept of "this" than I ;-)
>
>There are no hex literals for negative numbers, just as there are no
>decimal literals for negative number. A literal, by nature, in any
>base, is non-negative.
You are talking about what _is_, not what _can be_ ;-)
IMO a literal is a source-context-compatible string representing an abstract value
(which typically has an alternate representation in the running-program context).
AFAIK there is no law against representing negative numbers as such with whatever
literal spellings are deemed useful.
>
>If you disagree: Is 0xFFF6 a positive or a negative number?
That is conventionally a positive number, because the python 2.4 hex syntax
is interpreted that way, as it should be now. With a leading 16x prefix instead of 0x
the rules would/could change. See below.
I am trying to propose an alternate (additional, not replacement) syntax, which
you could call base-complement. The base is specified by a prefixed <base>x where
<base> is encoded in decimal. Zero is not a legal base, so there is no problem
recognizing current hex literals.
The digits following <base>x result from the numeric value's being encoded with
the base radix, and the most significant _must_ be zero or base-1 and may be repeated
leftwards as far as desired without changing the value, which is computed by something like:
For digits on the right side (following the <base>x):
>>> def bcdecode(s, B=10, digits='0123456789abcdefghijklmnopqrstuvwxyz'):
... if s == digits[0]: return 0
... acc = s[0].lower() == digits[B-1] and -B**len(s) or 0
... for i, c in enumerate(s[::-1]):
... acc += digits.index(c)*B**i
... return acc
...
For the whole literal (which you need, unless you are assuming you know the base
and that first digits are sign or sign leftwards-replications according to base-complement convention)
>>> def blitdec(s):
... xpos = s.lower().index('x')
... base = int(s[:xpos])
... return bcdecode(s[xpos+1:], base)
...
>>> blitdec('2x011')
3
>>> blitdec('2x00000011')
3
>>> blitdec('2x101')
-3
>>> blitdec('2x11111101')
-3
>>> blitdec('16x0fff6')
65526
>>> blitdec('16xffff6')
-10
>>> hex(blitdec('16x0fff6'))
'0xfff6'
>>> hex(blitdec('16xffff6'))
'-0xa'
Urk! ;-/
For backwards compatibility, hex will have to do that, but there IMO there should be
a base-complement output format available too, so e.g., (to give it a name)
baselit(blitdec('16xffff6'), 16) => '16xf6' #(normalized to single sign digit unless explicitly formatted)
BTW,
>>> blitdec('8x03')
3
>>> blitdec('8x73')
-5
>>> blitdec('10x03')
3
>>> blitdec('10x93')
-7
The point is a bit-visualization-friendly literal representation (when desired,
and for which you'd normally use base 2, 8, or 16 ;-) of all integers.
And also it could be nice to be able to write (impossible now)
>>> compiler.parse('x=16xffff6','single')
and get
Module(None, Stmt([Assign([AssName('x', 'OP_ASSIGN')], Const(-10))]))
instead of (the result of what you have to write now)
Module(None, Stmt([Assign([AssName('x', 'OP_ASSIGN')], UnarySub(Const(10)))]))
BTW, I see the code above needs some cleaning and another .lower() or two
but I am too lazy to fix or optimize, and the corresponding
literal-formatting code is left as an exercise ;-)
Regards,
Bengt Richter
More information about the Python-list
mailing list