Package: basemath
basemathA small python library to work with numbers of any baseInstall it using pip:pipinstallbasemathIf you need to work with hex, bin, oct, any-base numbers, you can use this simple python library. Any-base number - is the number with the base you need to use it.
Using this library (version 1.0) you can carry out basic operations like:plusminusmulAlso you canconvert a-base number to any other b-base. You can find decimal number from any-base number anytime.For example you need to find check sum for IP packet:# this is ip packet:packet='''45000034d5274000380600005fa77a0aac106429'''.upper()# convert it into bnum typepacket=bNUM(packet,16)# get 10 bnums with length 4 and same base 16parts=packet.get_k_bnums(10,4)# get sum of this 10 bnumsresult=bnum_sum(parts)# cut the head of result and sum it with the rest# to make result with length 4result=result.cutdown(4)# find check sum as FFFF - resultresult=bNUM('FFFF',16,4)-resultThe result will be check sum:'(F8F0).16'Consistance:bNUMclasslengthparameterto_lenmethodcutdownmethodmathoperationsothermethodsinitfunctionsadditionalfunctionsbNUMbNUM(value, base, length=None, cut=None)Use this class to carry out operations with any-base number.
You can createbnum(any-base number using bNUM class)using:Decimal number (integers only):number=10# or any integer you wantbase=2# or any base you want starting from 2bnum=bNUM(number,base)print(bnum)#>>'(1010).2'String representation of your any-base number:str_basenum='1010'base=2bnum=bNUM(str_basenum,base)print(bnum)>>'(1010).2'List representation of your any-base number:list_basenum=['1','0','1','0']base=2bnum=bNUM(list_basenum,base)print(bnum)>>'(1010).2'You can also pass list of bnums as a value:bnums=[bNUM('10',2),bNUM('10',2)]base=2bnum=bNUM(bnums,base)print(bnum)>>'(1010).2'As you can mention, the string output of bNUM object useing format (number).base: (10).10, (1010).2, (A).16 and etc
bNUM uses local list ORDER to represent and operate with any element of any base. ORDER list consists of strings that are representations of any-base digits:
ORDER = ['0', '1', '2', '3', '4', ..., 'A', 'B', 'C', ..., 'a', 'b', 'c', ..., !1A, !1B, !1C, ..........]THE ELEMENTS ARE CASE-SENSETIVE! SO YOU SHOULD PASS STINGS AND LISTS INTO bNUM KNOWING THAT, E.G. 'A' IS DIFFERENT THAN 'a':
'A' = 10, 'B' = 11, ..., 'Z' = 35, 'a' = 36, 'b' = 37, ..., 'z' = 61, '!1A' = 62, '!1B' = 63, ...*As you can see, starting after 'z' it goes '!1A' - is the syntax to use next other any-base digits.It goes as ![period of repeating number]letter
There are '!' signs to indicate the start of the new any-base digit that is out of standard range from 0 to 9, from A to Z and from a to z:String representationsDecimals0 - 90 - 9A - Z10 - 35a - z36 - 61!1A - !1Z62 - 87!1a - !1z88 - 113!2A - !2Z114 - 139!2a - !2z140 - 165......!1000A - !1000Z52010 - 52035!1000a - !1000z52036 - 52061So you can use up to 52061 base numbers.The attributes of bNUM object:string- string representation of number: bNUM(10, 2).string -> '1010'array- array representation of number: bNUM(10, 2).array -> ['1', '0', '1', '0']base- base of number: bNUM(10, 2).base -> 2decimal- decimal number representation: bNUM(10, 2).decimal -> 10length parameterlength=None (int)Use length parameter to keep this length of bnum. For example, if you pass number with zeros at the highest rank (e.g. '0001010') without length parameter, then this zeros is erased:string='0001010'base=2bnum=bNUM(string,base)print(bnum)>>'(1010).2'Than, use length parameter to keep this length:bnum=bNUM(string,base,length=7)print(bnum)>>'(0001010).2'Use length parameter to expand the length of your bnum, filling it with zeros:bnum=bNUM('1010',2,length=10)print(bnum,len(bnum))>>'(0000001010).2',10If you pass length less than your any-base number, then nothing happens. Length parameter is only working to keep or expand by zeros original length of any-base number:bnum=bNUM('01010',2,length=4)print(bnum)>>'(01010).2'To remove zeros from bnum usecutzerosmethod.to_lento_len(length) -> bNUMUse this method with your bnum to return new bnum with new or the same length. Again, the length can only be the same or expanded by filling with zeros:bnum1=bNUM('1010',2)bnum2=bnum1.to_len(10)print(bnum2)>>'(0000001010).2'cutdowncutdown(length) -> bNUMThe operation of cutdown can be defined by this algorithm:Take number A as input with length equals input_len, and reqired length equals output_lenSave elements with the index greater than output_lenMake new number B from this elements by adding zeros to the highest rank of the resulting numberMake new number C from elements that left in A (index less than output_length)Find sum: B + CIf sum length = output_len, then end of algorithm. If not, then cutdown sumFor example:
We have number 1010 of base 2. The cutdown to length = 3:
A = 1010
B = 001 (the first 1 from A expanded to length = 3)
C = 010 (the rest of A)
result := 001 + 010 = 011The cutdown to length = 2:
A = 1010
B = 10 (the first to numbers from A)
C = 10 (the rest elements from A)
sum := 10 + 10 = 100
Continuing...
A = 100
B = 01
C = 00
result := 01 + 00 = 01bnum1=bNUM('420',10)bnum2=bnum1.cutdown(2)# 04 + 20 = 24bnum3=bnum1.cutdown(1)# 42 + 0 = 42; 4 + 2 = 6bnum4=bnum1.cutdown(3)# the same as bnum1print(bnum2,bnum3,bnum4)>>'(24).10','(6).10','(420).10'You can pass int cut parameter creating new bNUM to use cutdown operation on created bnum.math operationsYou can find sum, multiplication, substraction of two bnums using standard python syntax:bnum1=bNUM('1010',2)# 10bnum2=bNUM('10',2)# 2print(bnum1+bnum2)# output = (1100).2  = 12print(bnum1*bnum2)# output = (10100).2 = 20print(bnum1-bnum2)# output = (1000).2  = 8Pay attention, if the minued is less then subtrahend (negative result of substraction), than the return will be decimal number of type int (not a bNUM):print(bnum2-bnum1)# output = -8You can carry out some bitwise operations like XOR, bitwise OR and bitwise AND (or just bitwise multiplication):bnum1=bNUM('1010',2)# 10bnum2=bNUM('10',2)# 2print(bnum1^bnum2)# 1010 XOR 10 = 1000 = 8print(bnum1|bnum2)# 1010 OR  10 = 1010 = 10print(bnum1&bnum2)# 1010 AND 10 = 1000 = 2other methodsUseto_base(base)to get new bNUM object with new base:bnum2  = bNUM('1010', 2)
 bnum16 = bnum2.to_base(16)
 bnum10 = bnum16.to_base(10)
 print(bnum2, bnum16, bnum10)

 >> (1010).2, (A).16, (10).10Use your bnums as standard python lists. Use index syntax to get bnum elements of type bNUM.But, pay attention!The indices here are not simple: the rank in bnums is left oriented, so are indices. Using indices you passes the power of digit position:
1 0 1 0 - binary number
3 2 1 0 - indices/powers of baseA F F 3 C 1 - hex number
5 4 3 2 1 0 - indices/powers of basebnum=bNUM('123456789',10)print(bnum.array,bnum.string)>>['1','2','3','4','5','6','7','8','9'],'123456789'print(bnum[0],type(bnum[0]))>>(9).10,<class'bNUM'>print(bnum[-1])>>(1).10forbinbnum:print(b,end=' ')>>(9).10,(8).10,(7).10,(6).10,(5).10,(4).10,(3).10,(2).10,(1).10Just think of it like you get item by index using reverted bnum.array.
Or you can use methodfrom_endpassing index as in standard array.
Don't forget that you can change single element of your bnum using index syntax.bnum1=bNUM('1010',2)print(bnum1,bnum1.decimal)>>(1010).2,10bnum1[0]=1print(bnum1,bnum1.decimal)>>(1011).2,11Use method insert and append like you use it with python lists.You can get copy of bNUM object using methodcopy:bnum1=bNUM('1010',2)bnum2=bnum1.copy()print(bnum2)>>(1010).2bnum1[0]=1print(bnum1,bnum2)>>(1011).2,(1010).2Or just copy parameters of another bnum to yours using methodcopy_here(bnum):bnum1=bNUM('1010',2)bnum2=bNUM('FFFF',16)bnum1.copy_here(bnum2)print(bnum1)>>(FFFF).16Fill bnum with any value useingfill(value)method (you can pass str or int < 10):bnum=bNUM('AAA',16)bnum.fill('F')print(bnum)>>(FFF).16Add amount of zeros you want to the lowest ranks using methodshift:bnum1=bNUM('111',2)bnum2=bnum1.shift(3)print(bnum1,bnum2)>>(111).2,(111000).2Usesplit(k, length)method to split bnum by k new bnums with the same length:bnum=bNUM('ABCDEF',16)print(bnum.split(3,2))>>[(AB).16,(CD).16,(EF).16]init functionsThere are functions to create bnum objects:zeros(length, base)andones(length, base).zeroscreates bNUM object filled with zeros.onescreates bNUM object filled with ones:bnum0=zeros(4,135)print(bnum0)>>(0000).135bnum1=ones(4,666)print(bnum1)>>(1111).666additional functionsThere functions like de2array, de2str, bnum_sum:de2array(decimal, base) - creates array of string representations of number of passed basede2str(decimal, base) - the same as the de2array, but returns stringbnum_sum(bnums) - returns sum of bnums in passed list