Posts: 1,845
Threads: 44
Joined: Aug 2002
My BIGINT library with (pureqb) support for BigIntegers has been released and is now downloadable from:
http://www.qbfm.cjb.net
Please look at it, use it, and tell me what you think of it!
And PLEASE: R.T.F.M. (for people who don't know what this means, it means 'Read the Manual').
The manual is README.TXT.
I expect at least wildcard, Na_Th_An, BlueKeyboard, aetherFox and Scrapyard to say what they think of it .
Posts: 3,343
Threads: 83
Joined: Mar 2003
Unfortunately for you, you are not allowed to use a library in my challenge. But you are welcome to use the functions contained (I'll give you a commendation if you can calculate 3000! with a function you submit.
Quote:Greetz go to:
Bluekeyboard
aetherFox
Mofu
wildcard
marcade
Plasma357
Josmul123
Na_Th_An
relsoft
Hexadecimal Disaster
Hard Rock
QBmaniac
akOOma
Scrapyard
You didn't include me in the list! :wink:
Posts: 3,288
Threads: 167
Joined: Nov 2001
Hmmm... The DL ain't workin'. :*)
Posts: 6,419
Threads: 74
Joined: Mar 2002
Same ... It ain't working.
Posts: 594
Threads: 11
Joined: Oct 2002
The qlb thing doesn't work (the same at Nathan and rel)...but i tried the .bas file and this one worked fine
B 4 EVER
Posts: 1,845
Threads: 44
Joined: Aug 2002
Hrmmm, very strange.
I get an 'Device not ready' error
Posts: 1,845
Threads: 44
Joined: Aug 2002
I already know what's wrong, don't open it with Winzip or something similar.
Instead, download total commander from http://fileforum.betanews.com/download.p...=945901171. Then open the package again. It should work now.
If it still doesn't work, here's the code:
Code: '
' BIGINT
'
' A small library having support for so-called 'big integers',
' which are unsigned data types consisting of a maximum of
' 262144 bits = 32768 bytes.
' Compare this with a normal integer: 16 bits = 2 bytes!
'
' Actually, this version of BIGINT has support for:
' - String integers (max value = 32768x a 9)
' Have fun!
'
' -Neo Deus Ex Machina
'
' X
' XXX
' X X
' XXX XXX
'
' HAR-SoftWare
'
' PS: Due to the fact that this is a pure-qb big integer
' library, I think you will get out of string space when
' using large big integers (like 10000!)
DECLARE FUNCTION SI.Add$(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.Subtract$(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.Multiply$(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.Divide$(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.Mod$(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.SmallDivide$(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.ShiftLeft$(StrInt AS STRING, Positions AS INTEGER)
DECLARE FUNCTION SI.ShiftRight$(StrInt AS STRING, Positions AS INTEGER)
DECLARE FUNCTION SI.Power$(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.IsGreater%(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.IsSmaller%(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.IsZero%(StrInt AS STRING)
DECLARE FUNCTION SI.IsEqual%(StrInt AS STRING, StrInt2 AS STRING)
DECLARE FUNCTION SI.IsEven%(StrInt AS STRING)
DECLARE FUNCTION SI.IsUnEven%(StrInt AS STRING)
DECLARE FUNCTION SI.Log10%(StrInt AS STRING)
CONST FALSE = 0
CONST TRUE = NOT FALSE
CONST LN.E = 2.718281828#
DEFINT A-Z
'$DYNAMIC
'$END_META
FUNCTION SI.Log10%(StrInt AS STRING)
SI.Log10% = LEN(StrInt) - 1
END FUNCTION
FUNCTION SI.IsEven%(StrInt AS STRING)
a% = LEN(StrInt)
IF a% = 0 THEN SI.IsEven% = FALSE: EXIT FUNCTION
char$ = MID$(StrInt, a%, 1)
vals% = VAL(char$)
IF vals% AND 1 THEN SI.IsEven% = FALSE ELSE SI.IsEven% = TRUE
END FUNCTION
FUNCTION SI.IsUnEven%(StrInt AS STRING)
a% = LEN(StrInt)
IF a% = 0 THEN SI.IsUnEven% = FALSE: EXIT FUNCTION
char$ = MID$(StrInt, a%, 1)
vals% = VAL(char$)
IF vals% AND 1 THEN SI.IsUnEven% = TRUE ELSE SI.IsUnEven% = FALSE
END FUNCTION
FUNCTION SI.IsEqual%(StrInt AS STRING, StrInt2 AS STRING)
IF StrInt = StrInt2 THEN SI.IsEqual% = TRUE ELSE SI.IsEqual% = FALSE
END FUNCTION
FUNCTION SI.IsZero%(StrInt AS STRING)
len1 = LEN(StrInt)
FOR c = 1 TO len1
IF MID$(StrInt, c, 1) <> "0" THEN
SI.IsZero% = FALSE
EXIT FUNCTION
END IF
NEXT c
SI.IsZero% = TRUE
END FUNCTION
FUNCTION SI.IsGreater%(StrInt AS STRING, StrInt2 AS STRING)
IF LEN(StrInt) > LEN(StrInt2) THEN
SI.IsGreater% = TRUE
EXIT FUNCTION
ELSEIF (LEN(StrInt) < LEN(StrInt2)) OR (StrInt = StrInt2) THEN
SI.IsGreater% = FALSE
EXIT FUNCTION
END IF
leng% = LEN(StrInt)
val1% = 0
val2% = 0
posi% = 1
DO
val1% = VAL(MID$(StrInt, posi%, 1))
val2% = VAL(MID$(StrInt2, posi%, 1))
posi% = posi% + 1
LOOP UNTIL val1% <> val2%
IF val1% > val2% THEN
SI.IsGreater = TRUE
EXIT FUNCTION
ELSE
SI.IsGreater = FALSE
END IF
END FUNCTION
FUNCTION SI.IsSmaller%(StrInt AS STRING, StrInt2 AS STRING)
IF LEN(StrInt) < LEN(StrInt2) THEN
SI.IsSmaller% = TRUE
EXIT FUNCTION
ELSEIF (LEN(StrInt) > LEN(StrInt2)) OR (StrInt = StrInt2) THEN
SI.IsSmaller% = FALSE
EXIT FUNCTION
END IF
leng% = LEN(StrInt)
val1% = 0
val2% = 0
posi% = 1
DO
val1% = VAL(MID$(StrInt, posi%, 1))
val2% = VAL(MID$(StrInt2, posi%, 1))
posi% = posi% + 1
LOOP UNTIL val1% <> val2%
IF val1% < val2% THEN
SI.IsSmaller% = TRUE
EXIT FUNCTION
ELSE
SI.IsSmaller% = FALSE
END IF
END FUNCTION
FUNCTION SI.Add$(StrInt AS STRING, StrInt2 AS STRING)
'
' This functions adds two String ints to eachother and
' returns the answer in a string int
'
'declare stuff
DIM len1 AS LONG, len2 AS LONG, maxlen AS LONG
DIM StrAns AS STRING, c AS LONG, char1 AS STRING, char2 AS STRING
len1 = LEN(StrInt)
len2 = LEN(StrInt2)
'pick out maximum length of the strings
IF len1<len2 THEN
maxlen = len2
StrAns = SPACE$(len2 + 1)
ELSE
maxlen = len1
StrAns = SPACE$(len1 + 1)
END IF
'calculate StrInt + StrInt2
over% = 0
' PRINT maxlen
FOR c = 1 TO maxlen
IF c <= LEN(StrInt) THEN char1 = MID$(StrInt, len1 - c + 1, 1) ELSE char1 = "0"
IF c <= LEN(StrInt2) THEN char2 = MID$(StrInt2, len2 - c + 1, 1) ELSE char2 = "0"
val1 = VAL(char1)
val2 = VAL(char2)
' print val1,val2
ans$ = LTRIM$(STR$(val1 + val2 + over%))
MID$(StrAns, LEN(StrAns) - c + 1, 1) = RIGHT$(ans$, 1)
IF LEN(ans$) > 1 THEN
over% = VAL(LEFT$(ans$, 1))
ELSE
over% = 0
END IF
NEXT c
StrAns = LTRIM$(StrAns)
IF over% > 0 THEN StrAns = LTRIM$(STR$(over%)) + StrAns
SI.Add$ = StrAns
END FUNCTION
FUNCTION SI.Subtract$(StrInt AS STRING, StrInt2 AS STRING)
'
' This functions subtracts two String ints to eachother and
' returns the answer in a string int
'
'declare stuff
DIM len1 AS LONG, len2 AS LONG, maxlen AS LONG
DIM StrAns AS STRING, c AS LONG, char1 AS STRING, char2 AS STRING
len1 = LEN(StrInt)
len2 = LEN(StrInt2)
'if the length of StrInt2 > StrInt then the answer is negative -> not allowed
IF len2 > len1 THEN SI.Subtract$ = "0": EXIT FUNCTION
'if the lengths are equal but StrInt2 is stil greater, quit too
IF (len2=len1) AND (VAL(LEFT$(StrInt2,1))>VAL(LEFT$(StrInt,1))) THEN SI.Subtract$="0":EXIT FUNCTION
'pick out maximum length of the strings
IF len1<len2 THEN
maxlen = len2
StrAns = SPACE$(len2 + 1)
ELSE
maxlen = len1
StrAns = SPACE$(len1 + 1)
END IF
'calculate StrInt - StrInt2
over% = 0
' PRINT maxlen
FOR c = 1 TO maxlen
IF c <= LEN(StrInt) THEN char1 = MID$(StrInt, len1 - c + 1, 1) ELSE char1 = "0"
IF c <= LEN(StrInt2) THEN char2 = MID$(StrInt2, len2 - c + 1, 1) ELSE char2 = "0"
val1 = VAL(char1)
val2 = VAL(char2)
' print val1,val2
ans$ = LTRIM$(STR$(10 + val1 - val2 + over%))
MID$(StrAns, LEN(StrAns) - c + 1, 1) = RIGHT$(ans$, 1)
IF LEN(ans$) > 1 THEN
over% = 0
ELSE
over% = -1
END IF
NEXT c
StrAns = LTRIM$(StrAns)
'IF (over% = 0) AND (LEN(StrAns) > 1) THEN StrAns = RIGHT$(StrAns, LEN(StrAns) - 1)
WHILE (LEFT$(StrAns, 1) = "0") AND (LEN(StrAns) > 1)
StrAns = RIGHT$(StrAns, LEN(StrAns) - 1)
WEND
SI.Subtract$ = StrAns
END FUNCTION
FUNCTION SI.Multiply$(StrInt AS STRING, StrInt2 AS STRING)
'
' This functions multiplies two String ints to eachother and
' returns the answer in a string int
'
'declare stuff
DIM len1 AS LONG, len2 AS LONG, maxlen AS LONG
DIM StrAns AS STRING, c AS LONG, char1 AS STRING, char2 AS STRING
DIM TempAns AS STRING
len1 = LEN(StrInt)
len2 = LEN(StrInt2)
'pick out maximum length of the strings
IF len1<len2 THEN
maxlen = len2
' StrAns = SPACE$(len2 + 1)
ELSE
maxlen = len1
' StrAns = SPACE$(len1 + 1)
END IF
StrAns = "0"
'calculate StrInt + StrInt2
over% = 0
' PRINT maxlen
FOR d = 1 TO len2
IF d>1 THEN
TempAns=STRING$(d-1,"0")
ELSE
TempAns=""
END IF
over% = 0
char2 = MID$(StrInt2, len2 - d + 1, 1)
val2 = VAL(char2)
FOR c = 1 TO len1
char1 = MID$(StrInt, len1 - c + 1, 1)
'print char1;" ";char2
val1 = VAL(char1)
ans$ = LTRIM$(STR$(val1 * val2 + over%))
'print ans$
TempAns = RIGHT$(ans$, 1) + TempAns
'print TempAns
IF LEN(ans$) > 1 THEN
over% = VAL(LEFT$(ans$, 1))
ELSE
over% = 0
END IF
NEXT c
IF over% > 0 THEN TempAns = LTRIM$(STR$(over%)) + TempAns
StrAns = SI.Add$(StrAns, TempAns)
'PRINT StrAns
NEXT d
StrAns = LTRIM$(StrAns)
SI.Multiply$ = StrAns
END FUNCTION
FUNCTION SI.Divide$(StrInt AS STRING, StrInt2 AS STRING)
'
' This functions divides two String ints to eachother and
' returns the answer in a string int
'
'declare stuff
DIM len1 AS LONG, len2 AS LONG, maxlen AS LONG
DIM StrAns AS STRING, c AS LONG, char1 AS STRING, char2 AS STRING
DIM TempD AS STRING, TempAns AS STRING, TempA AS STRING
len1 = LEN(StrInt)
len2 = LEN(StrInt2)
'check if the division will be good
IF len2 > len1 THEN
SI.Divide$ = "0"
EXIT FUNCTION
ELSEIF (len2 = len1) AND (VAL(LEFT$(StrInt,1))<VAL(LEFT$(StrInt2,1))) THEN
SI.Divide$ = "0"
EXIT FUNCTION
END IF
IF SI.IsZero(StrInt2) THEN
SI.Divide$ = "0"
EXIT FUNCTION
END IF
'pick out maximum length of the strings
IF len1<len2 THEN
maxlen = len2
' StrAns = SPACE$(len2 + 1)
ELSE
maxlen = len1
' StrAns = SPACE$(len1 + 1)
END IF
StrAns = ""
'calculate StrInt / StrInt2
over$ = ""
charlen = len2 - 1
' PRINT maxlen
'endofloop = len1
TempD = LEFT$(StrInt, charlen)
inhowmuch$ = ""
TempAns = ""
FOR c = charlen + 1 TO len1
TempD = TempD + MID$(StrInt, c, 1)
'PRINT "D-String:",TempD
inhowmuch$ = "0"
inhowmuch$ = SI.SmallDivide$(TempD, StrInt2)
'PRINT "I-String:",inhowmuch$
TempAns = TempAns + inhowmuch$
TempA = SI.Multiply$(inhowmuch$, StrInt2)
TempD = SI.Subtract$(TempD, TempA)
IF SI.IsZero(TempD) THEN TempD = ""
'PRINT "S-String:",TempD
NEXT c
'StrAns = TempAns
WHILE (LEN(TempAns) > 1) AND (LEFT$(TempAns, 1) = "0")
TempAns = RIGHT$(TempAns, LEN(TempAns) - 1)
WEND
StrAns = TempAns
SI.Divide$ = StrAns
END FUNCTION
FUNCTION SI.SmallDivide$(StrInt AS STRING, StrInt2 AS STRING)
' first check if the division is ok
IF SI.IsGreater%(StrInt2, StrInt) = TRUE THEN
SI.SmallDivide$ = "0"
EXIT FUNCTION
END IF
IF StrInt = StrInt2 THEN
SI.SmallDivide$ = "1"
EXIT FUNCTION
END IF
over$ = StrInt
times$ = "0"
DO
over$ = SI.Subtract(over$, StrInt2)
times$ = SI.Add(times$, "1")
LOOP UNTIL over$ = "0"
IF SI.Multiply(times$, StrInt2) <> StrInt THEN
SI.SmallDivide$ = SI.Subtract(times$, "1")
ELSE
SI.SmallDivide$ = times$
END IF
END FUNCTION
FUNCTION SI.Mod$(StrInt AS STRING, StrInt2 AS STRING)
'calculates StrInt MOD StrInt2
SI.Mod$ = SI.Subtract$(StrInt, SI.Multiply$(SI.Divide$(StrInt, StrInt2), StrInt2))
END FUNCTION
FUNCTION SI.ShiftLeft$(StrInt AS STRING, Positions AS INTEGER)
IF NOT(SI.IsZero(StrInt)) THEN SI.ShiftLeft$ = StrInt + STRING$(Positions, "0") ELSE SI.ShiftLeft$ = "0"
END FUNCTION
FUNCTION SI.ShiftRight$(StrInt AS STRING, Positions AS INTEGER)
IF LEN(StrInt) <= Positions THEN
SI.ShiftRight$ = "0"
EXIT FUNCTION
END IF
SI.ShiftRight$ = LEFT$(StrInt, LEN(StrInt) - Positions)
END FUNCTION
FUNCTION SI.Power$(StrInt AS STRING, StrInt2 AS STRING)
' calculates StrInt ^ StrInt2
DIM Remind AS STRING
DIM Pow AS STRING
DIM BaseN AS STRING
'some criteria
IF SI.IsZero(StrInt2) THEN SI.Power$ = "1" : EXIT FUNCTION
IF StrInt2 = "1" THEN SI.Power$ = StrInt : EXIT FUNCTION
Pow = StrInt2
BaseN = StrInt
Remind = "1"
DO
IF SI.IsUnEven(Pow) THEN 'uneven
Remind = SI.Multiply$(Remind, BaseN)
Pow = SI.Subtract$(Pow, "1")
END IF
Pow = SI.Divide$(Pow,"2")
BaseN = SI.Multiply$(BaseN, BaseN)
LOOP UNTIL Pow = "1"
SI.Power$ = SI.Multiply$(Remind, BaseN)
END FUNCTION
Copy and paste this into notepad and save as a *.bas file
Posts: 1,845
Threads: 44
Joined: Aug 2002
With some modifications, it could also be usable in VB, thus resulting in faster calculation and more string space!
Posts: 3,368
Threads: 195
Joined: Jan 2003
This looks cool. I did a similar thing but it only added and used 0's and 1's in string format instead of 0 to 9.
One thing you could try to do, though, is replace the strings with integers.
You'd first need to convert the number to a compressed format in an integer array by using AND or using some other way to get the bits.
Or you could just get every two bytes and make it an integer.
If you used four bytes (without conversion) or two bytes (with conversion), to make it as fast as possible, you'd need to create a carry mechanism which may not be worth it both in programming time and in computational time.
The best way, I think, would be to just give one byte of data for each integer so that your result is an integer as well.
Of course if you are using 32 bits, two bytes per integer and a result in a double integer would be better. But DOs is 16bit. :|
Peace cannot be obtained without war. Why? If there is already peace, it is unnecessary for war. If there is no peace, there is already war."
Visit www.neobasic.net to see rubbish in all its finest.
Posts: 6,419
Threads: 74
Joined: Mar 2002
Great work! It is robust, well coded, fast and really really smart. And sure, a port to VB should be direct. I guess you can directly paste the whole thing as a VB module
|