Interesting problem comparing strings with integer values...
Peter Abel
p-abel at t-online.de
Thu Jan 16 08:14:05 EST 2003
Chris Spencer <clspence at one.net> wrote in message news:<cvqb2vge6101f1l0sp20pmvdfgql84r1nt at 4ax.com>...
> Due to certain design constraints, I must be able to store both integers
> and floating point numbers as strings. These strings must be able to be
> compared correctly, so things like: "999"<"3432" are not possible.
> One option we thought of was padding the strings with zeros, so things
> like: "00000999"<"00003432" would work. This seems a bit hack-y to me. I was
> wondering if anyone has a more elegant solution to the problem?
>
> Chris.
As bit-representation results in wide strings, I tried it in hex and
seems to be successfull:
def n2s(number):
"""
Converts any number (int,float) to a string
in an near hex-representation
Doesn't work with float in exponential format
"""
# Get the signum of number by using 'and or trick'
signum=number<0 and -1 or 1
# convert int and float to the common float-format
# and make a string of it
num_str=str(abs(float(number)))
# Get the fixed and the fraction-part
(sfix,sfrac)=num_str.split('.')
# Convert both to an int
# considering the number's signum
fix=int(sfix)*signum
# Take the 7 most left decimal fraction-digits
frac=int((sfrac+'0000000')[:7])*signum
# Convert both to a 6-digits hex-String
fixum=('%06X'%fix)[-6:]
fractum=('%06X'%frac)[-6:]
# Since 2's complement changes order
# of negativ and positiv numbers, we
# need a signum represantation in the right order
# ord('+'), ord('-') is in wrong order too
sig=signum == 1 and 'p' or 'm'
return sig+fixum+sig+fractum
def s2n(snum):
"""
Converts "sig+fixum+sig+fractum" - format to float
"""
# Get the signum 1 or -1
signum = snum[0]=='p' and 1 or -1
prefix = signum == 1 and '00000000' or 'FFFFFFFF'
sfix=snum[1:7]
sfrac=snum[8:]
# We need prefix, to get the right sign by eval
fix=eval ('0x'+((prefix+sfix)[-8:]))
# frac has special case, when 0
if eval('0x'+sfrac):
# frac-sign must be reversed
frac=eval('0x'+((prefix+sfrac)[-8:]))*signum
else:
frac=0
fi='%d'%fix
# %07d is important
fra=('%07d'%frac)[:7]
return float(str(fi)+'.'+str(fra))
if __name__ == '__main__':
# remark lnum is allready sorted
lnum=[-1234.567 , -10.0 , -3 , 0 , 20.56,200]
# Conversion
lcv =map(n2s,lnum)
# Converted an sorted
lcvs=[]
lcvs[:]=lcv # A Copy
lcvs.sort()
# reconvert
lrcv=map(s2n,lcvs)
print 'Numbers :'
print lnum
print 'Converted :'
print lcv
print 'Sorted : (Hope there is no change to Converted!)'
print lcvs
print 'Reconverted:',lrcv
Here's the program's ouput:
---------------------------
>>> Numbers :
[-1234.567, -10.0, -3, 0, 20.559999999999999, 200]
Converted :
['mFFFB2EmA97B90', 'mFFFFF6m000000', 'mFFFFFDm000000',
'p000000p000000', 'p000014p557300', 'p0000C8p000000']
Sorted : (Hope there is no change to Converted!)
['mFFFB2EmA97B90', 'mFFFFF6m000000', 'mFFFFFDm000000',
'p000000p000000', 'p000014p557300', 'p0000C8p000000']
Reconverted: [-1234.567, -10.0, -3.0, 0.0, 20.559999999999999, 200.0]
Hope could help you.
-- Peter __
More information about the Python-list
mailing list