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