Using strings for math functions

E1bddb31000e459fb3ee5593fe067486
0
paul0n0n 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

Please log in or register to post a reply.

5225bc0c3bf66f4c275c332de6388d1f
0
SyntaxError 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?

254754b37f468a2926bffcd83bbbf1fa
0
z80 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).

E1bddb31000e459fb3ee5593fe067486
0
paul0n0n 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

A0c9c0649c5deacc0ae3b7f7721c94d2
0
starstutter 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.

E1bddb31000e459fb3ee5593fe067486
0
paul0n0n 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 (longGT(Right(a,Len(a)-1),b) == true){return L_ADD(Right(a,Len(a)-1),b);}
            }
            if (Left(b,1) == "-" && Left(a,1) != "-")
            {
                if (longGT(Right(b,Len(b)-1),a) == true){return L_ADD(Right(b,Len(b)-1),a);}
            }
            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";}
                    t = L_ADD(t,f);f = "";
                }
                for (int e = 1; e <= z; e++) { t = t + "0"; }
                p = L_ADD(t,p);t = "";
            }
            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);
        }
        public static string addPlaceHolders(string numToChange, int decimalsToAdd)
        {
            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;}
    }
}
6837d514b487de395be51432d9cdd078
0
TheNut 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.

8fd4a055522ce713cde7dd1cb4083cb2
0
martinsm 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).

E1bddb31000e459fb3ee5593fe067486
0
paul0n0n 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.

5225bc0c3bf66f4c275c332de6388d1f
0
SyntaxError 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.

820ce9018b365a6aeba6e23847f17eda
0
geon 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.)

E1bddb31000e459fb3ee5593fe067486
0
paul0n0n 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.

6837d514b487de395be51432d9cdd078
0
TheNut 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;
               addition -= 10;
          }
          else
               carry = 0;

          result.Add(addition);
     }

     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.

8676d29610e6c98d6dd2d9c38528cd9c
0
alphadog 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#.

8fd4a055522ce713cde7dd1cb4083cb2
0
martinsm 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++)

E1bddb31000e459fb3ee5593fe067486
0
paul0n0n 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
                // be to add the negitive sign infront of the outcome.
                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
                // be to add the negitive sign infront of the outcome.
                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

                    //Add "0"'s to 'Outcome'
                    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);
        }
E1bddb31000e459fb3ee5593fe067486
0
paul0n0n 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).

this is very helpful! Thanks.

254754b37f468a2926bffcd83bbbf1fa
0
z80 101 Aug 26, 2009 at 16:14