AtasoyWeb - Hüseyin Atasoy
AtasoyWeb
Hüseyin Atasoy'un Programlama Günlüğü

Uzun Tamsayı Sınıfı

Basamak sayısı sınırı olmadan tamsayılar üzerinde çarpma, toplama, bölme ve faktöryel alma işlemlerinin yapılabilmesini sağlayan cpp sınıfı.
C++ ile uzun tamsayı sınıfı

Bu sınıf yardımıyla sınırsız sayıda basamak içeren uzun tamsayılar oluşturabilir ve bu sayılarla toplama, çıkarma, çarpma gibi işlemler yapabilirsiniz. Ek olarak sınıf içerisinde, 4 basamaklı sayıların bile faktöryellerini hesaplayacak bir de fonksiyon var. Örneğin 1009 sayısının faktöryeli 27 saniyede hesaplandı ve sonuçta tam 2596 basamaklı bir sayı çıktı. Herhangi bir taşma olmaması için işlemlerin tümünü rakam rakam yaptırdım ve bölme işleminde rakam rakam gidilebilecek bir yöntem bulamadığımdan bölme işlemini tanımlamadım...

#include <iostream>
#include <string>
#include <stdlib.h> // itoa için

using namespace std;

class uzunts
{
/*
    Hüseyin Atasoy
    www.atasoyweb.net
    21/12/2009
*/
    //İki sayının biri diğerinden daha az basamak taşıyorsa ona 0 ekler.
    //örneğin 12 ve 3, 12 ve 03 olur.
    void basamakesitle(string& sayi1, string& sayi2, int& uzunluk)
    {
        if(sayi1.length()>sayi2.length())
        {
            uzunluk=sayi1.length();
            string ekle;
            ekle.append(uzunluk-sayi2.length(),'0');
            sayi2.insert(0,ekle);
        }
        else
        {
            uzunluk=sayi2.length();
            string ekle;
            ekle.append(uzunluk-sayi1.length(),'0');
            sayi1.insert(0,ekle);
        }
    }

    //String tipinde eşit basamaklı iki sayıyı karşılaştırır. En anlamlı
    //rakamlardan birbirlerine eşit olmayanlara rastladı mı sonuç döndürür.
    int hangisibuyuk(string& sayi1, string& sayi2, int uzunluk)
    {
        int rakam1,rakam2;
        for(int i=0; i<uzunluk; i++)
        {
            rakam1=atoi((sayi1.substr(i,1)).c_str());
            rakam2=atoi((sayi2.substr(i,1)).c_str());
            if(rakam1>rakam2) return 1; //ilk sayı daha büyük
            if(rakam1<rakam2) return 2; //ikinci sayı daha büyük
        }
        return 0; //buraya gelirse eşitler demektir, o zaman 0 döndür...
    }

    public:
    string sayi;

    uzunts(){}
    //constructor overloading; direk atama yapılmak istenirse
    uzunts(string degeri){ sayi=degeri; }

    uzunts operator + (uzunts x)
    {
        uzunts sonuc("");
        int rakam1,rakam2,tplm,uzunluk,elde=0;
        string snc,sayi1=sayi,sayi2=x.sayi;
        basamakesitle(sayi1,sayi2,uzunluk);

        for(int i=uzunluk-1; i>-1; i--)
        {
            snc=""; //her seferinde tekrar kullanmak için boşalt.
            rakam1=atoi((sayi1.substr(i,1)).c_str());
            rakam2=atoi((sayi2.substr(i,1)).c_str());
            tplm=rakam1+rakam2+elde;
            //iki rakamın ve eldenin toplamı en çok
            //9+9+9=27 olur yani 2 basamaklı.
            char b[3];
            itoa(tplm,b,10);
            snc.insert(0,b);
            if(tplm>=10) //Eğer toplam 2 basamaklıysa
            {
                //onlar basamağı elde olacak
                elde=atoi((snc.substr(0,1)).c_str());
                //diğeri de sonuca ait bir rakam
                sonuc.sayi.insert(0,snc.substr(1,1));
            }
            else
            {
                elde=0;
                //demek ki tek basamaklı
                sonuc.sayi.insert(0,snc.substr(0,1));
            }
        }
        //En son kalan 0 değilse başa koy.
        if(elde!=0) sonuc.sayi.insert(0,snc.substr(0,1));
        return sonuc; //geçmiş olsun, hesap tamamlandı...
    }

    uzunts operator - (uzunts x)
    {
        uzunts sonuc("");
        int rakam1,rakam2,fark,uzunluk,komsudan=0;
        string snc,sayi1=sayi,sayi2=x.sayi;
        bool eksi=false;
        basamakesitle(sayi1,sayi2,uzunluk);
        //Eğer küçük-büyük isteniyorsa büyük-küçük hesapla,
        //sonra başına - eklersin.
        if(hangisibuyuk(sayi1,sayi2,uzunluk)==2)
        {
            sayi2=sayi;
            sayi1=x.sayi;
            basamakesitle(sayi1,sayi2,uzunluk);
            eksi=true;
        }

        for(int i=uzunluk-1; i>-1; i--)
        {
            char b[3];
            rakam1=atoi((sayi1.substr(i,1)).c_str());
            rakam2=atoi((sayi2.substr(i,1)).c_str());
            fark=rakam1-rakam2-komsudan;
            //Onluğu alındığı halde hala büyükse veya eşitse
            if(rakam1-komsudan>=rakam2)
            {
                itoa(fark,b,10);
                komsudan=0;
            }
            else //altındaki rakamdan küçükse, komşudan onluk al.
            {
                itoa(10+fark,b,10);
                komsudan=1;
            }
            snc.insert(0,b);
                sonuc.sayi.insert(0,snc);
            snc="";
        }
        int i;
        //sondaki sıfıra kadar, soldaki tüm sıfırları sil
        for(i=0; i<uzunluk-1; i++)
            if(sonuc.sayi.at(i)!='0') break;
        sonuc.sayi.erase(0,i);
        //küçük-büyük istenmişse - koy
        if(eksi==true) sonuc.sayi.insert(0,"-");
        return sonuc; //geçmiş olsun, hesap tamamlandı...
    }

    uzunts operator * (uzunts x)
    {
        //tektek, alttaki her rakamın üstteki sayı ile çarpımını tutacak.
        uzunts sonuc,tektek;
        string snc,sifirekle,sayi1=sayi,sayi2=x.sayi;
        int rakam1,rakam2,tplm,elde=0;
        int uzunluk=sayi.length(),uzunluk2=sayi2.length();
        char b[3];
        for(int j=uzunluk2-1; j>-1; j--)
        {
            rakam2=atoi((sayi2.substr(j,1)).c_str());
            for(int i=uzunluk-1; i>-1; i--)
            {
                rakam1=atoi((sayi1.substr(i,1)).c_str());
                tplm=rakam1*rakam2+elde;
                itoa(tplm,b,10);
                snc.insert(0,b);
                if(tplm>=10) //Eğer toplam 2 basamaklıysa
                {
                    //onlar basamağı elde olacak
                    elde=atoi((snc.substr(0,1)).c_str());
                    tektek.sayi.insert(0,snc.substr(1,1));
                }
                else
                {
                    elde=0;
                    tektek.sayi.insert(0,snc.substr(0,1));
                }
                snc="";
            }
            //En son kalan 0 değilse başa koy.
            if(elde!=0) tektek.sayi.insert(0,itoa(elde,b,10));
            tektek.sayi.insert(tektek.sayi.length(),sifirekle);
            //burada classa ait yukardaki + operatorünü kullanmış oluyoruz.
            sonuc=sonuc+tektek;
            tektek.sayi="";
            elde=0;
            //Hani çarpmada alttaki sayıda her basamak atlandığında
            //çarpımı 1 basamak sola kaydırıyoruz ya, bu da o
            sifirekle.append(1,'0');
        }
        return sonuc; //geçmiş olsun, hesap tamamlandı...
    }

    //İşlemleri güzel gösteren bir fonksiyon da olsun bari
    void goster(uzunts uzunts1, uzunts uzunts2, uzunts sonuc, string islem)
    {
        cout<<endl;
        string ekle1,ekle2,ekle3;
        ekle1.append(sonuc.sayi.length(),'-');
        ekle2.append(sonuc.sayi.length()-uzunts1.sayi.length(),' ');
        ekle3.append(sonuc.sayi.length()-uzunts2.sayi.length(),' ');

        cout<<"\t"<<ekle2<<uzunts1.sayi<<endl;
        cout<<"     "<<islem<<"\t"<<ekle3<<uzunts2.sayi<<endl;
        cout<<"    ----"<<ekle1<<endl;
        cout<<"\t"<<sonuc.sayi;
        cout<<endl;
    }

    uzunts faktoryel(void)
    {
        uzunts alinan, sonuc("1"), bir("1");
        int uzunluk;
        alinan.sayi=sayi;
        basamakesitle(alinan.sayi,bir.sayi,uzunluk);
        //alinan sayi 1den büyükken...
        while(hangisibuyuk(alinan.sayi,bir.sayi,uzunluk)==1)
        {
            sonuc=sonuc*alinan;
            alinan=alinan-bir;
            //whiledaki hangisibuyuk fonksiyonu için
            basamakesitle(alinan.sayi,bir.sayi,uzunluk);
        }
        int i;
        uzunluk=sonuc.sayi.length();
        //basamak eşitlemeden kaynaklanan soldaki değersiz
        for(i=0; i<uzunluk-1; i++)
            if(sonuc.sayi.at(i)!='0') break; //sıfırları sil
        sonuc.sayi.erase(0,i);
        return sonuc;
    }
};

int main()
{
    uzunts a("2334233532324883824928384");
    uzunts b("48765984758787");
    uzunts c;

    c=a+b;
    c.goster(a,b,c,"+"); //cout<<c.sayi<<endl;

    cout<<endl<<endl;

    c=a*b;
    c.goster(a,b,c,"*");

    cout<<endl<<endl<<"307! = ";

    uzunts d("307");
    cout<<(d.faktoryel()).sayi;

    cout<<endl;
    return 0;
}
Yazar: Hüseyin Atasoy
Posted: 31/01/2010 10:32
Keywords: cpp uzun tamsayı sınıfı, yüzlerce basamaklı sayılar, büyük sayılarda işlem yapma

Leave Comment

 
You are replying to comment #-1. Click here if you want to cancel replying.

 

Comments (3)

mustafa
Reply
27/12/2010 21:51
#1

Çok güzel bir program olmuş, ellerinize sağlık. C  üzerine birkaç örnek daha olsa çok güzel olur. Şuan her ne kadar anlayamasakta inşallah ileride anlayabiliriz :)

Hüseyin Atasoy
Reply
27/12/2010 23:16
#2

Zaman bulursam bu kategoriyi kod örnekleriyle dolduracağım.

mustafa
Reply
30/12/2010 14:44
#3

Bizler için çok iyi olur. Kolaylıklar dilerim şimdiden..Teşekkürler.

 
Şu an bu sayfada 1, blog genelinde 9 çevrimiçi ziyaretçi bulunuyor. Ziyaretçiler bugün toplam 120 sayfa görüntüledi.
 
Sayfa 46 sorgu ile 0.038 saniyede oluşturuldu.
Atasoy Blog v4 © 2008-2024 Hüseyin Atasoy