Base10 to Base...

Share your advanced PureBasic knowledge/code with the community.
jeslar360
User
User
Posts: 20
Joined: Thu Aug 28, 2008 6:24 am

Base10 to Base...

Post by jeslar360 »

I am not sure how many of you will find these functions useful, but I am posting them anyway. I know there are built in functions for converting back and forth from Hex/Base64/Base2(Binary)...but these functions seem to be very unfriendly to variables.

So, I designed these 2 procedures for converting back and forth...as well as some examples on usage...

First, converting to a base...I did this so there could be other bases besides the ones listed above...

Code: Select all

#_NUM_BASE_10   = "0123456789" ; This is just to give it a default

Procedure.s Int2Base(InVal.l, Valid.s=#_NUM_BASE_10)
  Base.l = Len(Valid)
  RemVal = InVal
  OutVal.s
  While RemVal
    OutVal = Mid(Valid, ((RemVal % Base) + 1), 1) + OutVal
    RemVal = ((RemVal-(RemVal % Base)) / Base)
  Wend
  If Not OutVal
    OutVal = "0"
  EndIf
  ProcedureReturn(OutVal)
EndProcedure
Then converting from any base back to Base 10 (regular integer)...

Code: Select all

#_NUM_BASE_10   = "0123456789" ; This is just to give it a default

Procedure.l Base2Int(InVal.s, Valid.s=#_NUM_BASE_10, UseCase=#False)
  Base.l = Len(Valid)
  If Not UseCase
    Valid = UCase(Valid)
    InVal = UCase(InVal)
    Debug "Not Case Sensitive"
  EndIf
  For i = 1 To Len(InVal)
    Chk.s   = Mid(InVal, i, 1)
    Pos     = FindString(Valid, Chk, 1)
    If Not Pos
      Debug "ERROR: Unsupported Character at Position " + Str(i)
      Break
    Else
      OutVal = (OutVal * Base) + (Pos - 1)
    EndIf
  Next
  ProcedureReturn(OutVal)
EndProcedure
And here, are some examples of how to use the functions in other functions...

I am showing Hex and Base64...just for examples

Code: Select all

#_NUM_BASE_16   = "0123456789ABCDEF"
#_NUM_BASE_64   = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"

Procedure Hex2Int(HexIn.s)
  ProcedureReturn(Base2Int(HexIn, #_NUM_BASE_16))
EndProcedure

Procedure.s Int2Hex(InVal)
  ProcedureReturn(Int2Base(InVal, #_NUM_BASE_16))
EndProcedure

Procedure Base64ToInt(B64In.s)
  ProcedureReturn(Base2Int(B64In, #_NUM_BASE_64, #True)) 
EndProcedure

Procedure.s Int2Base64(InVal)
  ProcedureReturn(Int2Base(InVal, #_NUM_BASE_64))
EndProcedure
The 3rd parameter in Base2Int is #False by default, that means Case Insensitive. That is fine for HEX, and BIN, but not for Base64...so we need to set the Case Sensitive to #True
User avatar
skywalk
Addict
Addict
Posts: 4220
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Base10 to Base...

Post by skywalk »

Get the heck outta here? I just wrote this last night. :cry:
Thanks, your Base2Int approach is a bit faster as I was starting from the right side of the number to convert.
Then I was using the dreaded Pow() function in an integer expression and fought for an hour before I added a "0.0 + " in front. Then the calc worked correctly.

Code: Select all

#alphanum36$ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Procedure.s SF_NumToBase36(x.i)
  ; Convert positive integer to base36 string.
  Protected.s r$
  If x > 0
    While x <> 0
      r$ = Mid(#alphanum36$, (x % 36) + 1, 1) + r$
      x / 36
    Wend
  Else
    r$ = "0"
  EndIf
  ProcedureReturn r$
EndProcedure

Procedure.i SF_Base36ToNum(base$)
  ; Convert base36 string to positive integer.
  Protected.i i, x, blen
  x = FindString(#alphanum36$, Right(base$, 1)) - 1  ; get last character
  blen = Len(base$)
  For i = blen - 1 To 1 Step -1
    x = 0.0 + x + Pow(36, (blen - i)) * (FindString(#alphanum36$, Mid(base$, i, 1)) - 1)
    ;   Must use "0.0 + " to force a double calc. Otherwise, wrong result!
  Next i
  ProcedureReturn x
EndProcedure
Debug SF_NumToBase36(100)  ; 2S
Debug SF_Base36ToNum("2S") ; 100
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
jeslar360
User
User
Posts: 20
Joined: Thu Aug 28, 2008 6:24 am

Re: Base10 to Base...

Post by jeslar360 »

I completely understand the frustration. This is actually my 3rd time writing a base converter...the code from the last two got lost...they were all locked to a specific base (Hex, and Bin)...I thought to make it this way this time, because I knew I would be doing a lot of back and forth encoding between multiple bases in the near future, and wanted to take the Write It Once, Use It For Everything approach.

The problem is, its the SIMPLE things that are often overlooked, because we (as humans) tend to think "It can't be THAT simple!"

But it is quite true, that the simplest approach is often the best...so figured I would share my moment of insight with everyone :)
jamba
Enthusiast
Enthusiast
Posts: 144
Joined: Fri Jan 15, 2010 2:03 pm
Location: Triad, NC
Contact:

Re: Base10 to Base...

Post by jamba »

cool, thanks for sharing!
-Jon

Fedora user
But I work with Win7
Post Reply