Re: Question About Z-Level Number Thingie

new topic     » goto parent     » topic index » view thread      » older message » newer message

Colin Taylor wrote:

>Here is a slight improvement of my original routine (recursion retained)
>and a slight improvement of your second routine (doesn't need the reverse()
>function).  It passes the sanity test, but still doesn't like negative
>numbers.
>
>constant CHAR = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
>
>function convert_base(integer num, integer base)
>    sequence out_str
>    out_str = ""
>    if num >= base then
>        out_str = convert_base(floor(num/base), base)
>    end if
>    return out_str & CHAR[remainder(num, base)+1]
>end function

<PICKYMODE=PETPEEVE>

Maybe this is just me, but I don't see why the convert_base() function has
to be recursive. Every time it calls itself, it has to re-allocate space for
num, base and out_str. I guess I don't see how that's "better" -- especially
since base retains the same value on each recursive call, which is rather
inefficient. Generally, I'm pretty sure it's more efficient to code a
routine with "while" loop, rather than trying to make it recursive. (If I'm
wrong, though, let me know!)

</PICKYMODE>

And as for handling negative values, well, I guess I'm just going to "cheat"
on this one. The two's complement stuff would only work for base-2 derived
number systems, so I'm just adding a sign character to the value. That way,
it'll work no matter what number system we're using.

>function read_base(sequence num, integer base)
>    integer out_num, len
>    len = length(num)
>    out_num = 0
>    for i = 1 to len do
>        out_num += (find(num[i], CHAR)-1)*power(base, len-i)
>    end for
>    return out_num
>end function

Cool, thanks for getting that reverse() call outta there! smile


-- my revised version, covering the full range of Euphoria integers positive
and negative...

constant NUM_CHAR = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

type base_type(integer x)
   return x >= 2 and x <= length(NUM_CHAR)
end type

function int_to_base_n(integer int, base_type base)
integer sign
sequence base_n

   if int < 0 then
      sign = '-'
      int = -int
   else
      sign = '+'
   end if

   base_n = ""
   while int >= base do
      base_n = prepend(base_n, NUM_CHAR[remainder(int,base)+1])
      int = floor(int/base)
   end while

   return sign & prepend(base_n, NUM_CHAR[int+1])
end function

function base_n_to_int(sequence base_n, base_type base)
integer len, int
   len = length(base_n)

   int = 0
   for pos = 2 to len do
      int += (find(base_n[pos], NUM_CHAR)-1) * power(base, len-pos)
   end for

   if base_n[1] = '+' then
      return int
   elsif base_n[1] = '-' then
      return -int
   end if
end function


-- sanity test
sequence string
integer result

for base = 2 to 36 do
   printf(1, "[Base %d]\n", base)
   for number = -100 to 100 do
      string = int_to_base_n(number, base)
      printf(1, "%s\n", {string})
      result = base_n_to_int(string, base)
      if number != result then
         printf(1, "%d != %d", {number, result})
         abort(0)
      end if
   end for
   puts(1, '\n')
end for

puts(1, "\nYay!\n")


Now, if somebody could figure out how to handle floating-point values with
this thing...

Hep yadda,
Gabriel Boehme

----------
We'll never get rich by hard work; but, we'll never get rich without it.

Robert Fripp
----------

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu