0
101 Aug 22, 2009 at 16:50

need some help optimizing my code. When I took this on I had no idea how hard simple math is. It is mostly complete, with the exception of dividing decimals, i think it’s done. I’m just wondering if there is a cleaner easier way to produce the same outcome, it needs to be faster.

;Main String math functions
Function L_DIVIDE$(a$,b$,length); partial functionality (dividing decimals does not work for now, everything else does) negTrigger = 0:trig = 0 If Left$(a$,1) = "-" And Left$(b$,1) = "-" Then a$ = Right$(a$,Len(a$)-1):b$ = Right$(b$,Len(b$)-1) If Left$(a$,1) = "-" Then negTrigger = 1:a$ = Right$(a$,Len(a$)-1) If Left$(b$,1) = "-" Then negtrigger = 1:b$ = Right$(b$,Len(b$)-1) RightSideDecimalCountOfa = rsdc(a$)
RightSideDecimalCountOfb = rsdc(b$) LeftSideDecimalCountOfa = lsdc(a$)
LeftSideDecimalCountOfb = lsdc(b$) If longGT(a$,b$) = True Then trig = 1 trigger = 0 If RightSideDecimalCountOfb <> 0 Then a$ = removeDecimal$(a$,RightSideDecimalCountOfa)
talc = Len(a$) a$ = replaceDecimal$(a$,RightSideDecimalCountOfa,RightSideDecimalCountOfb)
b$= removeDecimal$(b$,RightSideDecimalCountOfb) If talc > Len(a$) Then cdph = talc - Len(a$) If talc < Len(a$) Then cdph = Len(a$) - talc-1 EndIf If trig = 1 Then cdph = 0 RightSideDecimalCountOfa = rsdc(a$)
RightSideDecimalCountOfb = rsdc(b$) LeftSideDecimalCountOfa = lsdc(a$)
LeftSideDecimalCountOfb = lsdc(b$) z = 1 While RightSideDecimalCountOfa <> 0 And Left$(a$,1) <> "." And z <> Len(a$)
If Left$(a$,1) = "0" Then a$= Right$(a$,Len(a$)-1)
z = z + 1
Wend
For z = 1 To RightSideDecimalCountOfa
b$= b$ + "0"
Next
a$= removeDecimal$(a$,RightSideDecimalCountOfa) ;a$ = removeDecimal$(a$,RightSideDecimalCountOfa)
;b$= removeDecimal$(b$,RightSideDecimalCountOfb) While Left$(a$,1) = "0" a$ = Right$(a$,Len(a$)-1) zerroCount = ZerroCount + 1 Wend If a$ = b$Return 1:trigger = 0 For z = 1 To length If a$ = 0 Then Return p$If a$ = "" Then Return p$tc=1 While longGT(b$,a$) = True a$ = L_MULTIPLY$(a$,10)
If trigger = 0 Then
p$= p$ + "0" + ".":trigger = 1
For zzz = 1 To cdph
p$= p$ + "0"
Next
Else
p$= p$ + "0"
EndIf
Wend
c = 0
d$= "" While longGT(d$,a$)= False c = c + 1 d$ = L_MULTIPLY$(b$,c)
If longGT(d$,a$) = True Then c = tc:Goto skip
tc = c
Wend
c = 1
.skip
d$= L_MULTIPLY$(b$,c) a$ = L_SUB$(a$,d$) If trigger = 1 Then p$ = p$+ c If trigger = 0 Then If trig = 1 Then p$ = p$+ c p$ = p$+ ".":trigger = 1 For zzz = 1 To cdph p$ = p$+ "0" Next If trig = 0 Then p$ = p$+ c EndIf If Len(p$) >= length Then Goto skip2
a$= L_MULTIPLY$(a$,10) Next .skip2 If negTrigger = 1 Then p$ = "-"+p$Return p$

End Function
Function L_ADD$(a$,b$) ;fully functional [Long Addition] negtrigger = 0 ;If Left$(a$,1) = "0" Then Return b$
If Left$(a$,1) = "-" And Left$(b$,1) <> "-" Then
If longGT(Right$(a$,Len(a$)-1),b$) = True Then p$= L_SUB(Right$(a$,Len(a$)-1),b$):Return "-"+p$
Return L_SUB(b$,Right$(a$,Len(a$)-1))
EndIf
If Left$(b$,1) = "-" And Left$(a$,1) <> "-" Then
If longGT(Right$(b$,Len(b$)-1),a$) = True Then p$=L_SUB(Right$(b$,Len(b$)-1),a$):Return "-"+p$
Return L_SUB(a$,Right$(b$,Len(b$)-1))
EndIf
If Left(b$,1) = "-" And Left(a$,1) = "-" Then negtrigger = 1
da = testDecimal(a$,1):db = testDecimal(b$,1)
If da > db Then larm = da-db:lar = da
If db > da Then larm = db-da:lar = db
If db < da Then b$= addPlaceHolders$(b$,larm) If da < db Then a$ = addPlaceHolders$(a$,larm)
a$= removeDecimal(a$,lar):b$= removeDecimal(b$,lar)
If Left$(a$,1) = "-" Then a$= Right$(a$,Len(a$)-1)
If Left$(b$,1) = "-" Then b$= Right$(b$,Len(b$)-1)
a1 = Len(a$):b1 = Len(b$)
If a1 > b1 Then largest = a1
If b1 > a1 Then largest = b1
If a1 = b1 Then largest = a1
For z = 0 To largest
If z <= a1-1 Then
n1 = Mid$(a$,a1-z,1)
Else
n1 = 0
EndIf
If z <= b1-1 Then
n2 = Mid$(b$,b1-z,1)
Else
n2=0
EndIf
n3 = n1+n2+remander
t$= n3 p$ = Right$(t$,1)+p$t1 = Len(t$)
If t1-1 > 0 Then
t$= Left$(t$,t1-1) Else t$ = ""
EndIf
remander = t$Next If Left$(p$,1) = "0" Then p$ = Right$(p$,Len(p$)-1) If da<>0 Or db <>0 Then p$ = addDecimal$(p$,lar)
If negtrigger = 1 Then p$= "-"+p$
Return p$End Function Function L_SUB$(a$,b$)  ;fully functional    [ Long Subtraction ]
negtrigger = 0
If longLT(a$,b$) = True And Left$(a$,1) <> "-" And Left$(b$,1) <> "-" Then negtrigger = 1:tb$=b$:b$=a$:a$=tb$
;   If Len(a$)<Len(b$) Then tb$=b$:b$=a$:a$=tb$
If Left$(a$,1) = "-" And Left$(b$,1) = "-" And longGT(a$,b$) = True Then Return L_ADD(a$,b$)
If Left$(a$,1) = "-" And Left$(b$,1) <> "-" Then
If longGT(Right$(a$,Len(a$)-1),b$) = True Then Return L_ADD$(Right$(a$,Len(a$)-1),b$) EndIf If Left$(b$,1) = "-" And Left$(a$,1) <> "-" Then If longGT(Right$(b$,Len(b$)-1),a$) = True Then Return L_ADD$(Right$(b$,Len(b$)-1),a$)
EndIf
da = testDecimal(a$,1):db = testDecimal(b$,1)
If da > db Then larm = da-db:lar = da
If db > da Then larm = db-da:lar = db
If db < da Then b$= addPlaceHolders$(b$,larm) If da < db Then a$ = addPlaceHolders$(a$,larm)
a$= removeDecimal(a$,lar):b$= removeDecimal(b$,lar)
If Left$(a$,1) = "-" Then a$= Right$(a$,Len(a$)-1)
If Left$(b$,1) = "-" Then b$= Right$(b$,Len(b$)-1)
a1 = Len(a$):b1 = Len(b$)
If a1 > b1 Then largest = a1
If b1 > a1 Then largest = b1
If a1 = b1 Then largest = a1
For z = 0 To largest-1
If z <= a1-1 Then
n1 = Mid$(a$,a1-z,1)
Else
n1 = 0
EndIf
If z <= b1-1 Then
n2 = Mid$(b$,b1-z,1)
Else
n2=0
EndIf
n3 = (n1-remander)-n2
If n3 < 0 Then
n3 = 10 + n3:remander =1
Else remander = 0 :EndIf
t$=n3:p$ = Right$(t$,1)+p$Next If Left$(p$,1) = "0" Then p$ = Right$(p$,Len(p$)-1) If da<>0 Or db <>0 Then p$ = addDecimal$(p$,lar)
If negtrigger = 1 Then p$= "-"+p$
Return p$End Function Function L_MULTIPLY$(a$,b$) ; fully functional (negative, decimal, positive, and all combinations)  [ Long Multiply ]
negTrigger = 0
If Left$(a$,1) = "-" And Left$(b$,1) = "-" Then a$= Right$(a$,Len(a$)-1):b$= Right$(b$,Len(b$)-1)
If Left$(a$,1) = "-" Then negTrigger = 1:a$= Right$(a$,Len(a$)-1)
If Left$(b$,1) = "-" Then negtrigger = 1:b$= Right$(b$,Len(b$)-1)
da = testDecimal(a$,1) :If da <> 0 Then a$ = removeDecimal$(a$,da)
db = testDecimal(b$,1) :If db <> 0 Then b$ = removeDecimal$(b$,db)
dec = da+db
For z = 0 To Len(b$)-1 n2 = Mid$(b$,Len(b$)-z,1)
For y = 0 To Len(a$)-1 n1 = Mid$(a$,Len(a$)-y,1)
n3 = n1*n2: f$= n3 For e = 1 To y f$ = f$+ "0" Next t$ = L_ADD$(t$,f$):f$ = ""
Next
For e = 1 To z
t$= t$ + "0"
Next
p$= L_ADD$(t$,p$):t$= "" Next If Left$(p$,1) = "0" Then p$ = Right$(p$,Len(p$)-1) If dec <> 0 Then p$ = addDecimal$(p$,dec)
If negTrigger = 1 Then p$= "-"+p$
Return p$End Function Function longGT(a$,b$);complete [ Long greater than ] If testDecimal(a$,0) = False And testDecimal(b$,0) = False Then a$ = makeEL$(a$,b$) b$ = makeEL$(b$,a$) EndIf If A$ > b$Return True Return False End Function Function longLT(a$,b$);complete [ Long less than ] If testDecimal(a$,0) = False And testDecimal(b$,0) = False Then a$ = makeEL$(a$,b$) b$ = makeEL$(b$,a$) EndIf If A$ < b$Return True Return False End Function Function longSin$(a$,b$)   ; [ Long sine ]
lp$=LongPower$(a$,3) lf$= longFactor(3)
Stop
lD$= L_DIVIDE$(lp$,lf$,10)
b$= L_SUB$(a$,lD$)
tt$= L_ADD$(L_MULTIPLY$(b$,2),1)
c = 0
m$= 3 .loop2: m$ = L_ADD(m$,2) If c = 1 Then lp$ =LongPower$(a$,m$) lf$= longFactor(m$) lD$ = L_DIVIDE$(lp$,lf$,10) b$ = L_SUB$(a$,lD$) c = 2 ;b$ = L_SUB$(b$,longDiv$(LongPower$(b$,3),longFactor$(m$),10)):c = 2 EndIf If c = 0 Then lp$ =LongPower$(a$,m$) lf$= longFactor(m$) lD$ = L_DIVIDE$(lp$,lf$,10) b$ = L_ADD$(a$,lD$) c = 1 ;b$ = L_ADD$(b$,longDiv$(LongPower$(b$,3),longFactor$(m$),10)):c = 1 EndIf If c = 2 Then c = 1 If m$<=tt$Then Goto loop2 Return b$
End Function
Function LongPower$(a$,b)
ta$= a$
For z = 1 To b-1
a$= L_MULTIPLY$(a$,ta$)
Next
Return a$End Function Function longFactor$(a$) ta$ = a$: x$ = "1"
.loop:m$= L_ADD$(m$,1) x$ = L_MULTIPLY$(x$,m$) If m$ <> a$Then Goto loop Return x$
End Function

;Helper functions
Function makeEL$(x$,y$) ;complete a1 = Len(x$):b1 = Len(y$) If a1 > b1 Or a1 = b1 Return x$
For z = 1 To b1-a1
x$= "0"+x$
Next
Return x$End Function Function testDecimal(a$,x);complete
f = Len(a$) Select True Case x = 0 For z = 1 To f If Mid$(a$,z,1) = "." Then Return True Next Return False Case x = 1 For z = 0 To f-1 If Mid$(a$,f-z,1) = "." Then Return z Next Case x = 2 For z = 1 To f If Mid$(a$,z,1) = "." Then Return z Next End Select Return 0 End Function Function removeDecimal$(a$,b) ;complete If b = 0 Then Return a$
a$= Left$(a$,Len(a$)-(b+1)) + Right$(a$,b)
Return a$End Function Function addDecimal$(a$,b) ;complete While Len(a$) < b
a$= "0" + a$
Wend
a$= Left$(a$,Len(a$)-b)+ "." + Right$(a$,b)
Return a$End Function Function addPlaceHolders$(numToChange$,decimalsToAdd) For z = 1to decimalsToAdd numToChange$ = numToChange$+ "0" Next Return numToChange$
End Function
Function CountDecimalPlaceHolder(a$) trigger = 0 For z = 1 To Len(a$)
If Mid$(a$,z,1) = "." Then trigger = 1: z = z + 1
If trigger = 1 And Mid$(a$,z,1) = "0" Then count = count + 1
If trigger = 1 And Mid$(a$,z,1) <> "0" Then Return count
Next
Return count
End Function
Function additionalPlaceHolders(a$,b$)
z = 1
While longGT(b$,Left$(a$,z))=True And b$ <> Left$(a$,z)
count = count + 1
z = z + 1
If z = Len(a$) Then Return 0 Wend Return count End Function Function CleanLDecimal$(a$) While Left$(a$,1) <> "." a$ = Right$(a$,Len(a$) -1) Wend Return a$
End Function
Function RSDC(A$) For PLACE = 1 To Len(A$)
If Mid$(A$,Len(A$)-(PLACE-1),1)= "." Then Return PLACE Next Return 0 End Function Function LSDC(A$)
For PLACE = 1 To Len(A$) If Mid$(A$,PLACE,1) = "." Then Return PLACE Next Return 0 End Function Function REPLACEDECIMAL$(NUM$,LS,RS) TEMP$ = Mid$(NUM$,1,LS) + "." + Mid$(NUM$,LS,RS)
Return TEMP\$
End Function


#### 17 Replies

0
101 Aug 23, 2009 at 17:35

Before going though your code, may I ask what the ultimate goal you are trying to achieve is? Are you trying to support numbers with high or unlimited precision and range? Do you want to support end user expression capability? Or are you trying to achieve something else entirely?

0
101 Aug 23, 2009 at 19:48

VB is bad for fast low level functions. Perhaps it would be better to write the code in C or assembler and put it in a DLL. Then you can use that DLL with VB (assuming you really need VB).

0
101 Aug 23, 2009 at 20:23

SyntaxError - high to unlimited precision.

z80 - That is a good idea, wonder if c# would be just as good as c

0
101 Aug 23, 2009 at 23:15

@paul0n0n

z80 - That is a good idea, wonder if c# would be just as good as c

If I’m not mistaken, C# is a very heavyweight language, making it a poor choice for low level functions where you need raw speed. Again though, this is just what I’ve heard about it.

0
101 Aug 24, 2009 at 02:48

Well, I’m not sure if I used c# correctly. but there are no syntax errors, so I’m pretty sure it will work. Here is the c# code. I’m sure I missed some things like correct conversion of strings to integers and the reverse. But if some one could test to see accuracy and maybe help improve, that would be awesome. thanks. should be easy to port to c with this, I’m not very good at c and I’m just starting in c#. If the below code works that is a plus. I’m not sure how to test a dll in c#… still a noob at it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace StringMathLibrary
{
public class StringMathClass
{
public static string L_DIVIDE(string a, string b,int length)
{
int negTrigger = 0;
int trig = 0;
if (Left(a,1)== "-" && Left(b,1) == "-")
{
a = Right(a, Len(a) - 1);
b = Right(b, Len(b) - 1);
}
if (Left(a, 1) == "-")
{
negTrigger = 1;
a = Right(a, Len(a) - 1);
}
if (Left(b, 1) == "-")
{
negTrigger = 1;
b = Right(b, Len(b) - 1);
}
int RightSideDecimalCountOfa = rsdc(a);
int RightSideDecimalCountOfb = rsdc(b);
int LeftSideDecimalCountOfa = lsdc(a);
int LeftSideDecimalCountOfb = lsdc(b);
if (longGT(a, b) == true)
{
trig = 1;
}
int trigger = 0;
int cdph = 0;
if (RightSideDecimalCountOfb != 0)
{
a = removeDecimal(a, RightSideDecimalCountOfa);
int talc = Len(a);
a = replaceDecimal(a, RightSideDecimalCountOfa, RightSideDecimalCountOfb);
b = removeDecimal(b, RightSideDecimalCountOfb);
if (talc > Len(a)){cdph = talc - Len(a);}
if (talc < Len(a)){cdph = Len(a) - talc - 1;}
}
if (trig == 1) { cdph = 0; }
RightSideDecimalCountOfa = rsdc(a);
RightSideDecimalCountOfb = rsdc(b);
LeftSideDecimalCountOfa = lsdc(a);
LeftSideDecimalCountOfb = lsdc(b);
int z = 1;
while (RightSideDecimalCountOfa != 0 && Left(a, 1) != "." && z != Len(a))
{
if (Left(a, 1) == "0") { a = Right(a, Len(a) - 1); }
z++;
}
for (int i = 1; 1 <= RightSideDecimalCountOfa; i++) { b = b + "0"; }
a = removeDecimal(a, RightSideDecimalCountOfa);
int zerroCount = 0;
while (Left(a, 1) == "0")
{
a = Right(a, Len(a) - 1);
zerroCount++;
}
if (a == b) { return "1"; }
string p = "";
int tc;
int c;
string d;
bool exit = false;
for (int i = 1; i <= length; i++)
{
while (Left(a, 1) == "0") { a = Right(a, Len(a) - 1); }
if (a == "") { return p; }
tc = 1;
while (longGT(b, a) == true)
{
a = L_MULTIPLY(a,"10");
if (trigger == 0)
{
p = p + "0" + ".";
trigger = 1;
for (int iz = 1; iz <= cdph; iz++) { p = p + "0"; }
}
else { p = p + "0"; }
}
c = 0;
d = "";
exit = false;
while (longGT(d, a) == false && exit == false)
{
c++;
d = L_MULTIPLY(b, Convert.ToString(c));
if (longGT(d, a) == true)
{
c = tc;
exit = true;
}
if (exit == false) { tc = c; }
}
if (exit == false) { c = 1; }
d = L_MULTIPLY(b, Convert.ToString(c));
a = L_SUB(a, d);
if (trigger == 1) { p = p + c; }
if (trigger == 0)
{
if (trig == 1) { p = p + c; }
p = p + ".";
trigger = 1;
for (int iz = 1; iz <= cdph; i++) { p = p + "0"; }
if (trig == 0) { p = p + c; }
}
if (Len(p) >= length)
{
if (negTrigger == 1) { p = "-" + p; }
return p;
}
a = L_MULTIPLY(a, "10");
}
if (negTrigger == 1) { p = "-" + p; }
return p;
}
public static string L_ADD(string a, string b)
{
int negTrigger = 0;
string p = "";
int larm = 0;
int lar = 0;
if (Left(a, 1) == "-" && Left(b, 1) != "-")
{
if (longGT(Right(a, Len(a) - 1), b) == true)
{
p = "-"+L_SUB(Right(a,Len(a) - 1),b);
return p;
}
return L_SUB(b, Right(a, Len(a) - 1));
}
if (Left(b, 1) == "-" && Left(a, 1) != "-")
{
if (longGT(Right(a,Len(a)-1),b) == true)
{
p ="-" + L_SUB(Right(b,Len(b)-1),a);
return p;
}
return L_SUB(a,Right(b,Len(b)-1));
}
if (Left(b,1)=="-" && Left(a,1)=="-"){negTrigger = 1;}
int da = testDecimal(a,1);
int db = testDecimal(b,1);
if (da > db){larm = da-db;lar = da;}
if (db > da){larm = db-da;lar = db;}
if (db < da){b = addPlaceHolders(b,larm);}
if (da < db){a = addPlaceHolders(a,larm);}
a = removeDecimal(a,lar);
b = removeDecimal(b,lar);
if (Left(a,1) == "-"){ a = Right(a,Len(a)-1);}
if (Left(b,1) == "-"){ b = Right(b,Len(b)-1);}
int a1 = Len(a);
int b1 = Len(b);
int largest= 0;
if (a1 > b1) {largest = a1;}
if ( b1>a1){largest = b1;}
if (a1==b1){largest = a1;}
int n1;int n2;int n3;string t;int remander = 0;int t1;
for (int i = 0; i <= largest; i++)
{
if (i <= a1-1){
n1 = int.Parse(Mid(a,a1-i,1));
}else{n1 = 0;}
if (i <= b1-1){
n2 = int.Parse(Mid(b,b1-i,1));
}else{n2 = 0;}
n3 = n1+n2+remander;
t = Convert.ToString(n3);
p = Right(t,1)+p;
t1 = Len(t);
if (t1-1 > 0){t = Left(t,t1-1);}else{t = "";}
remander = int.Parse(t);
}
if (Left(p,1)=="0"){p = Right(p,Len(p)-1);}
if (da!=0 || db != 0) { p = addDecimal(p,lar);}
if (negTrigger == 1){p = "-"+p;}
return p;
}
public static string L_SUB(string a, string b)
{
int negTrigger = 0;string p = "";string tb = "";int da = 0; int db = 0;int larm= 0;int lar= 0;
if (longLT(a,b) == true && Left(a,1) != "-" && Left(b,1) != "-"){ negTrigger = 1;tb=b;b=a;a=tb;}
if (Left(a,1) == "-" && Left(b,1) == "-" && longGT(a,b) == true){ return L_ADD(a,b);}
if (Left(a,1) == "-" && Left(b,1) != "-")
{
}
if (Left(b,1) == "-" && Left(a,1) != "-")
{
}
da = testDecimal(a,1);db = testDecimal(b,1);
if (da > db){larm = da-db;lar = da;}
if (db > da){larm = db-da;lar = db;}
if (db < da){b = addPlaceHolders(b,larm);}
if (da < db){a = addPlaceHolders(a,larm);}
a = removeDecimal(a,lar);b = removeDecimal(b,lar);
if (Left(a,1) == "-"){a = Right(a,Len(a)-1);}
if (Left(b,1) == "-"){b = Right(b,Len(b)-1);}
int a1 = Len(a);int b1 = Len(b);int largest = 0;
if (a1 > b1){largest = a1;}
if (b1 > a1){largest = b1;}
if (a1 == b1){largest = a1;}
int n1; int n2; int n3;int remander = 0;string t;
for (int z = 0; z<=largest-1;z++)
{
if (z <= a1-1){n1 = int.Parse(Mid(a,a1-z,1));}else{n1 = 0;}
if (z <= b1-1){n2 = int.Parse(Mid(b,b1-z,1));}else{n2=0;}
n3 = (n1-remander)-n2;
if (n3 < 0){n3 = 10 + n3;remander =1;}else{remander = 0;}
t=Convert.ToString(n3);p = Right(t,1)+p;
}
if (Left(p,1) == "0"){p = Right(p,Len(p)-1);}
if (da!=0 || db != 0){p = addDecimal(p,lar);}
if (negTrigger == 1) { p = "-" + p; }
return p;
}
public static string L_MULTIPLY(string a, string b)
{
int negTrigger = 0;
string p = "";
if(Left(a,1) == "-" && Left(b,1) == "-"){ a = Right(a,Len(a)-1);b = Right(b,Len(b)-1);}
if (Left(a,1) == "-") {negTrigger = 1;a = Right(a,Len(a)-1);}
if (Left(b,1) == "-") {negTrigger = 1;b = Right(b,Len(b)-1);}
int da = testDecimal(a,1);
if (da != 0){a = removeDecimal(a,da);}
int db = testDecimal(b,1);
if (db != 0){b = removeDecimal(b,db);}
int dec = da+db;
int n1;int n2;int n3;string f;string t = "";
for (int z = 0; z<=Len(b)-1;z++)
{
n2 = int.Parse(Mid(b,Len(b)-z,1));
for (int y = 0;y<=Len(a)-1;y++)
{
n1 = int.Parse(Mid(a,Len(a)-y,1));
n3 = n1*n2; f = Convert.ToString(n3);
for (int e = 1; e<=y;e++){f = f + "0";}
}
for (int e = 1; e <= z; e++) { t = t + "0"; }
}
if (Left(p,1) == "0"){ p = Right(p,Len(p)-1);}
if (dec != 0){p = addDecimal(p,dec);}
if (negTrigger == 1){p = "-"+p;}
return p;
}
public static bool longGT(string a, string b)
{
if (testDecimal(a, 0) == 0 && testDecimal(b, 0) == 0)
{
a = makeEL(a, b);
b = makeEL(b, a);
}
int result = a.CompareTo(b);
if (result > 0) { return true; }
return false;
}
public static bool longLT(string a, string b)
{
if (testDecimal(a, 0) == 0 && testDecimal(b, 0) == 0)
{
a = makeEL(a, b);
b = makeEL(b,a);
}
int result = a.CompareTo(b);
if (result < 0) { return true; }
return false;
}
// Helper functions
public static string makeEL(string x, string y)
{
int a1 = Len(x); int b1 = Len(y);
if (a1 > b1 || a1 == b1) { return x; }
for (int z = 1; z <= b1 - a1; z++) { x = "0" + x; }
return x;
}
public static int testDecimal(string a, int x)
{
int f = Len(a);
if (x == 0)
{
for (int z = 1; z <= f; z++) { if (Mid(a, z, 1) == ".") { return 1; } }
return 0;
}
if (x == 1)
{
for (int z = 1; z <= f - 1; z++) { if (Mid(a, f - z, 1) == ".") { return z; } }
}
if (x == 2)
{
for (int z = 1; z <= f; z++) { if (Mid(a, z, 1) == ".") { return z; } }
}
return 0;
}
public static string removeDecimal(string a, int b)
{
if (b == 0) { return a; }
return Left(a,Len(a)-(b+1))+Right(a,b);
}
public static string addDecimal(string a, int b)
{
while (Len(a) < b) { a = "0" + a; }
return Left(a, Len(a) - b) + "." + Right(a, b);
}
{
for (int z = 1; z <= decimalsToAdd; z++) { numToChange = numToChange + "0"; }
return numToChange;
}
public static int CountDecimalPlaceHolder(string a)
{
bool trigger = false;int count = 0;
for (int z = 1; z <= Len(a); z++)
{
if (Mid(a, z, 1) == ".") { trigger = true; z++; }
if (trigger == true && Mid(a, z, 1) == "0") { count++; }
if (trigger == true && Mid(a, z, 1) != "0") { return count; }
}
return count;
}
public static int additionalPlaceHolders(string a, string b)
{
int z = 1;
int count = 0 ;
while (longGT(b, Left(a, z)) == true && b != Left(a, z))
{
count++;
z++;
if (z == Len(a)) { return 0; }
}
return count;
}
public static string CleanLDecimal(string a)
{
while (Left(a, 1) != ".") { a = Right(a, Len(a) - 1); }
return a;
}
public static int rsdc(string a)
{
for (int place = 1; place <= Len(a); place++) { if (Mid(a, (Len(a) - (place - 1)), 1) == ".") { return place; } }
return 0;
}
public static int lsdc(string a)
{
for (int place = 1; place <= Len(a); place++) { if (Mid(a, place, 1) == ".") { return place; } }
return 0;
}
public static string replaceDecimal(string num, int ls, int rs)
{
string temp;
temp = Mid(num, 1, ls) + "." + Mid(num, ls, rs);
return temp;
}
// string functions
static string Right(string s, int count)
{
string newString = String.Empty;
if (s != null && count > 0)
{
int startIndex = s.Length - count;
if (startIndex > 0)
newString = s.Substring(startIndex, count);
else
newString = s;
}
return newString;
}
static string Left(string s, int count)
{
string newString = string.Empty;
if (s != null && count > 0)
{
int startIndex = 1;
if (startIndex > 0)
newString = s.Substring(startIndex, count);
else
newString = s;
}
return newString;
}
static string Mid(string s, int start, int end)
{
string newString = string.Empty;
if (s != null && start > 0 && end > 0)
{
int totalIndex = start + end;
if (totalIndex <= s.Length)
newString = s.Substring(start, end);
else
newString = s;
}
return newString;
}
static int Len(string s){return s.Length;}
}
}

0
179 Aug 24, 2009 at 10:35

.NET usually isn’t that far behind C in performance (10% is the usual figure thrown around). I’ve been converting my C++ engine over to C# and it’s been a pleasant experience. All my procedural algorithms run almost on par with the C++ counterpart. In Paul’s case, the strings are weighing the program down. Although even in C, dealing with strings is expensive compared to base data types. paul0n0n, read up on Binary Coded Decimal (BCD) arithmetic. It’s like string arithmetic, but you operate on a byte array instead. Most operations can also be performed using logic (OR, XOR, AND, etc…) which is really fast compared to “school-book arithmetic”. You don’t have to convert between numbers and strings, so that’s an instant boost there. If you implement full BCD, you can store 2 digits in a single byte (4 bits per digit), although management gets a little more complicated. Once you convert to that format, you should already see a boost. Avoid creating copies of objects (ie: substring(…)).

Also, in case you just want a quick fix, there are C# libraries out there that do this sort of thing. See: http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic.

0
101 Aug 24, 2009 at 10:38

I would suggest using byte[] or uint[] array for storing digits of large integer (as 8-bit or 32-bit digits), not strings. Then manipulating array elements will be easier and without any string maniuplation functions (that are heavy on memory allocations).

0
101 Aug 24, 2009 at 14:12

martinsm - That may be so, but it can be more complicated. I started out with trying to use array’s but gave it up as… well maybe I could figure it out. at any rate I’m not too worried about memory consumption at this point. I just want to know how to use it, then maybe improve upon it.

TheNut - Using array’s isn’t a bad idea, but are array’s re-sizable in c#? If not I’m not sure how to make it essentially (hardware determined) infinite.

0
101 Aug 24, 2009 at 14:37

@paul0n0n

SyntaxError - high to unlimited precision. z80 - That is a good idea, wonder if c# would be just as good as c

Well if you really want it to be fast I used to program in 8086 asm and there were BCD assembly instructions on the 8086. I assume they have also carried over to the 32 bit architecture. However I’m not sure how you get to them from C#. If I remember C# can call C DLLs so if you write an asm program, use C calling convention and compile it as a DLL you should be able to get it to work. I’m not the best expert on C# though.

Edit: It pays the read the thread :) Ok well I guess I added at least a little.

0
101 Aug 24, 2009 at 14:43

If you need to convert between your bignum data and strings a lot, it might be a good idea to store it as decimal numbers in memory too, since the base conversion is quite costly.

(I have no idea what any of the above code is doing, since it was too painful to read.)

0
101 Aug 24, 2009 at 14:57

geon - i know its painful, it’s just simple arithmetic using strings. It’s complicated and just, well messy. I will comment the c# code to death, hopefully that will help.

0
179 Aug 24, 2009 at 15:43

@paul0n0n

are array’s re-sizable in c#

Basic array’s don’t have a “resize” method, although it wouldn’t be difficult to write a method to do it. Instead, you can use List<byte> with Add / Insert calls. .NET will manage the memory for you, and in some ways it will be efficient since it will allocate more than you actually need, giving you buffer space to work with. The trick here is to store the number backwards in the list. That is, the most significant number is stored at the end of the the list.

Ex: 123.456
List[0] = 6, List[1] = 5, List[2] = 4, etc…

This way you progressively add into the list rather than insert, which is quite expensive.

This will make your arithmetic calculations much easier. A really basic example is provided below. This example assumes both number1 and number2 are the same size, are both positive (note, you can use Two’s Compliment to perform addition of a negative value), and have a mantissa at the same location, which is represented by some sort of “mantissa index” class member (ie: you don’t include the decimal in the list).

public List<byte> add (List<byte> number1, List<byte> number2)
{
List<byte> result = new List<byte>();

// Add from left to right (remember, this number will be backwards)
byte carry = 0;
for (int i = 0; i < number1.Count; ++i)
{
byte addition = number1[i] + number2[i] + carry;
if ( addition > 9 )
{
carry = 1;
}
else
carry = 0;

}

return result;
}

public string ToString (List<byte> number)
{
string result = "";
for (int i = number.Count - 1; i >= 0; --i)
result += number[i];
return result;
}


Pretty clean eh? Just throw in the extra part to handle negatives and varying number sizes and that should get you going.

0
101 Aug 24, 2009 at 16:01

If you are going to do this with strings in C#, consider using StringBuilder. I didn’t pour through your code, but generally and when used appropriately, it can help alleviate the overhead of repeated rebuilds of string objects since they are immutable in .NET C#.

0
101 Aug 24, 2009 at 16:55

Yes, arrays are resizeable in C#:

byte[] arr = new byte[10];
Array.resize(ref arr, 100);
Console.WriteLine(arr); // will print 100


But you should use List<T> anyway, because it has other nice properties and methods (like std::vector<T> in C++)

0
101 Aug 24, 2009 at 18:12

ok, here is the commented code for just Division.. I know there are errors in it as I came across a few that I didn’t fix.

public static string L_DIVIDE(string a, string b,int length)
{
//For example perposis 'a' = "0000000.0034"
//For example perpeses 'b' = "29"
// 'a' is the numerator
// 'b' is the denominator
// 'length' is the max number of decimal places to be calculated,
// as most fractions are endlessly repeating.

//Initialize Integers
int RightSideDecimalCountOfa;
int RightSideDecimalCountOfb;
int LeftSideDecimalCountOfa;
int LeftSideDecimalCountOfb;
int cdph = 0;
int talc;
int z = 1;
int zerroCount = 0;
int tc;
int c;
//Initialize Strings
string Outcome = "";
string d;
//Initialize bools
bool trigger = false;
bool negTrigger = false;
bool trig = false;
bool exit = false;

//Find out if the outcome is going to be a Negitive number
if (Left(a,1)== "-" && Left(b,1) == "-")
{
// if both a and b are negitive the outcome will be positive.
// so remove the negitive sign from both a and b.
a = Right(a, Len(a) - 1);
b = Right(b, Len(b) - 1);
}
if (Left(a, 1) == "-")
{
// If only a is negitive the outcome will be negative.
// So turn the negTrigger to true and remove the negitive sign from a.
// With the negTrigger to true the last step before returning the outcome will
negTrigger = true;
a = Right(a, Len(a) - 1);
}
if (Left(b, 1) == "-")
{
// If only b is negitive the outcome will be negative
// So turn the negTrigger to true and remove the negitive sign from b.
// With the negTrigger to true the last step before returning the outcome will
negTrigger = true;
b = Right(b, Len(b) - 1);
}

//Find the Decimal point's position from the right side
RightSideDecimalCountOfa = rsdc(a); //rsdc is Right Side Decimal Count
RightSideDecimalCountOfb = rsdc(b);
//Find the decimal point's position from the left side
LeftSideDecimalCountOfa = lsdc(a);//lsdc is Left Side Decimal Count
LeftSideDecimalCountOfb = lsdc(b);

// If a is greater than b then the cdph (Common Decimal point Place Holder) is triggered
// to be set to 0.  This is so that wholeNumber/wholeNumber works.
if (longGT(a, b) == true)
{
trig = true;
}

// This section is used to deturmain the decimal point's placeholder (cdph)
// if  'a' is a fraction and 'b' is a fraction.  (not working properly)
if (RightSideDecimalCountOfb != 0)
{
a = removeDecimal(a, RightSideDecimalCountOfa);
talc = Len(a);
a = replaceDecimal(a, RightSideDecimalCountOfa, RightSideDecimalCountOfb);
b = removeDecimal(b, RightSideDecimalCountOfb);
if (talc > Len(a)){cdph = talc - Len(a);}
if (talc < Len(a)){cdph = Len(a) - talc - 1;}
}
if (trig == true) { cdph = 0; }

//Find the Decimal point's position from the right side.
//This is done for a second time for the fraction/fraction cenerio
RightSideDecimalCountOfa = rsdc(a); //rsdc is Right Side Decimal Count
//if 'a' = "000000.0034" rsdc(a) would return 4.
RightSideDecimalCountOfb = rsdc(b);
//Find the decimal point's position from the left side
LeftSideDecimalCountOfa = lsdc(a);//lsdc is Left Side Decimal Count
//if 'a' = "000000.0034" lsdc(a) would return 6.
LeftSideDecimalCountOfb = lsdc(b);

//If a = "0000000.0034" then remove all the "0"'s on the left side.
//So that a = ".0034".  It's not really necesary but is here as a precaution.
while (RightSideDecimalCountOfa != 0 && Left(a, 1) != "." && z != Len(a))
{
if (Left(a, 1) == "0") { a = Right(a, Len(a) - 1); }
z++;
}

//Make 'b' have an equal right side decimal point place holders as 'a'
//So if 'a' = ".0034 and 'b' = "29"  after this 'b' = "290000"
for (int i = 1; 1 <= RightSideDecimalCountOfa; i++) { b = b + "0"; }

//if 'a' = ".0034" afther this removes the decimal point 'a' = 0034
a = removeDecimal(a, RightSideDecimalCountOfa);

//Change 'a' from "0034" to "34" and count how many zerro's were removed
//zerroCount = 2
while (Left(a, 1) == "0")
{
a = Right(a, Len(a) - 1);
zerroCount++;
}

//If 'a' is equal to 'b' then it will always be "1" so return that.
if (a == b) { return ("1"); }

//Now the Division.  'length' is used here as a basis and not as the strict guid.
for (int i = 1; i <= length; i++)
{
//remove any "0"'s that happen to pop up infront of 'a'
//this avoids an endless loop if 'a' ever happens to equal "0" or "00" or "00...00"
while (Left(a, 1) == "0") { a = Right(a, Len(a) - 1); }

//If 'a' is empty as it should be from the above statement were 'a' would equal "0"
//return the 'Outcome'.
if (a == "") { return (Outcome); }

//Make 'a' greater then 'b' if it is not already
while (longGT(b, a) == true)
{
//multiply 'a' by "10"
a = L_MULTIPLY(a,"10");

//add's the standard "0." to the 'Outcome' if it hasn't been done.
//Then add the necisary place holders.
if (trigger == false)
{
Outcome = Outcome + "0" + ".";
trigger = true;

//Adds the place holders to the 'Outcome'.
for (int iz = 1; iz <= cdph; iz++) { Outcome = Outcome + "0"; }
}
else { Outcome = Outcome + "0"; }// if 'a' is multiplied by 10 then the 'Outcome' needs a "0" added.
}

//Reset for next pass.
tc = 1;         //'tc' (temp count)
c = 0;          //'c' (count)
d = "";         //'d' (temp denominator) so that 'b' is never changed.
exit = false;   //'exit' (exit loop trigger)

//'c' is the um well..
//Say 'Outcome' ="0.01272" 'c' is the individial '1' then '2' then '7' ect.
//I don't know if this part is works in c#.  I had to make some changes from
//my original basic structure. There could be a possable infinit loop here.
//If 'a' = "1000000000" and 'b' = "1" then 'c' would have to count upto 1000000000.
while (longGT(d, a) == false && exit == false)
{
c++;  //Increase 'c' by 1.
d = L_MULTIPLY(b, Convert.ToString(c)); //Multiply 'b' by 'c' and put it in 'd'

//Increase 'c' until 'd' is greater then 'a'.
if (longGT(d, a) == true)
{
c = tc;  // 'c' equals the last 'c' so that 'd' is not greater then 'a'.
exit = true; //'exit' the loop.
}
if (exit == false) { tc = c; } // 'tc' = 'c', skip this if 'exit' is true.
}
// if (exit == false) { c = 1; }  //I don't think This is needed.

d = L_MULTIPLY(b, Convert.ToString(c)); //Multiply 'b' by 'c' and put it in 'd'
a = L_SUB(a, d); //Subtract 'a' from 'd' and replace 'a'

//Append 'c' to 'Outcome' if 'Outcome' already has "0.".
if (trigger == true) { Outcome = Outcome + c; }

//If 'Outcome' doesn't have "0." then 'c' is on the left side of the decimal point.
if (trigger == false)
{
//Append 'c' to 'Outcome'
if (trig == true) { Outcome = Outcome + c; }
Outcome = Outcome + "."; //Add the decimal point
trigger = true;  //The decimal point has been added

for (int iz = 1; iz <= cdph; i++) { Outcome = Outcome + "0"; }

//Append 'c' to 'Outcome' if nothing else was done.
if (trig == false) { Outcome = Outcome + c; }
}

// If 'Outcome' has 'length' decimal places then
if (Len(Outcome) >= length)
{
//If 'Outcome' should be negative then add "-" to the front of it.
if (negTrigger == true) { Outcome = "-" + Outcome; }

//Return 'Outcome'.
return (Outcome);
}

//Increase the size of 'a' by "10" for the next pass.
a = L_MULTIPLY(a, "10");
}
//If 'Outcome' should be negative then add "-" to the front of it.
if (negTrigger == true) { Outcome = "-" + Outcome; }

//Return 'Outcome'.
return (Outcome);
}

0
101 Aug 24, 2009 at 21:52

@TheNut

use List<byte> with Add / Insert calls. .NET will manage the memory for you, and in some ways it will be efficient since it will allocate more than you actually need, giving you buffer space to work with. The trick here is to store the number backwards in the list. That is, the most significant number is stored at the end of the the list.

Ex: 123.456
List[0] = 6, List[1] = 5, List[2] = 4, etc…

This way you progressively add into the list rather than insert, which is quite expensive.

This will make your arithmetic calculations much easier. A really basic example is provided below. This example assumes both number1 and number2 are the same size, are both positive (note, you can use Two’s Compliment to perform addition of a negative value), and have a mantissa at the same location, which is represented by some sort of “mantissa index” class member (ie: you don’t include the decimal in the list).